How to autoscale a service on CPU and memory

Turn on horizontal autoscaling for an Ownkube deployment: set min and max replicas, CPU and memory targets, and see why idle replicas barely touch your bill.

Ownkube team | | How-To | 5 min

A single replica is fine until traffic isn’t steady: a launch post spikes requests for an hour, then it’s quiet again. Rather than picking one fixed size and living with either overpaying at 3am or falling over at noon, Ownkube can add and remove replicas of a deployment automatically, based on how hard CPU and memory are actually working.

This guide turns on horizontal autoscaling for a web or worker deployment, explains what the CPU and memory targets actually control, and covers what it does to your bill.

TL;DR

  • Autoscaling is a per-deployment setting: min and max replica counts, plus a target CPU percentage and a target memory percentage.
  • Ownkube adds replicas when either target is exceeded and removes them as load drops, never going below your minimum or above your maximum.
  • New replicas roll in with zero-downtime rollouts, so scaling up (or deploying a new revision while scaled up) doesn’t drop traffic.
  • On Ownkube Compute’s metered billing, CPU and memory bill on actual per-minute usage, so a replica sitting idle between traffic spikes costs close to nothing.
  • Set it from the deployment’s Settings tab, or the same fields from the CLI via a manifest update.

Turn on autoscaling

  1. Open the deployment (a web or worker type; jobs and databases don’t autoscale) and go to its Settings tab.
  2. Find the Autoscaling card and flip its switch on.
  3. Set Min replicas and Max replicas. Min is your floor, the number of replicas that stay running even at zero load; max is your ceiling, how far Ownkube can scale up under sustained pressure.
  4. Set Target CPU % and Target Memory %. These are the utilization levels, as a percentage of each replica’s resource limit, that trigger a scale-up when crossed.
  5. Save. The change applies without downtime; existing replicas keep serving traffic while the new target takes effect.
# manifest.yaml, applied with: okctl deploy update <deployment-id> -f manifest.yaml
appConfig:
  autoscaling:
    enabled: true
    minReplicas: 1
    maxReplicas: 5
    targetCPUUtilizationPercentage: 70
    targetMemoryUtilizationPercentage: 80

How the targets actually work

Autoscaling here is horizontal: Ownkube changes how many replicas of your deployment are running, not the size of any single replica. Each replica still runs at the CPU and memory limits you set on the Resources tab; the target percentages are how full those limits need to get before another replica joins.

  • If Target CPU % is 70 and a replica’s CPU usage sits above 70% of its limit for a sustained period, Ownkube adds a replica and spreads load across both.
  • The same logic applies independently to Target Memory %. Whichever trigger fires first drives the scale-up; either one dropping back below target (with both below target) is what allows scaling back down.
  • Replicas never drop below Min replicas, even at zero traffic, and never exceed Max replicas, even under sustained load. Set the max to whatever ceiling keeps you comfortable, both for capacity and for spend.

A good starting point for most web apps is a target in the 60 to 80% range on both CPU and memory: low enough to add capacity before things actually feel slow, high enough that you’re not scaling up on every minor blip.

Scaling and deploys stay zero-downtime

Autoscaling shares the same rolling-update mechanics as a normal deploy: a new replica has to pass its health check before it starts receiving traffic, and an old replica is only removed after its replacement is ready. That holds whether the new replica showed up because you pushed a commit or because load crossed your CPU target, so a traffic spike and a deploy landing at the same time don’t fight each other or drop requests.

What autoscaling does to your bill

On Ownkube Compute, metered billing measures both CPU and memory on actual per-minute usage, not on the size you provisioned. That changes the economics of scaling up compared to a platform that bills per fixed instance-hour regardless of load:

  • A replica that autoscaling added during a traffic spike and then removed an hour later only metered for that hour, not for the rest of the month.
  • A replica sitting at your minimum during quiet hours draws almost nothing on CPU, since the meter reflects what’s actually used, not the limit it’s allowed to reach.
  • If a workload runs hot around the clock instead of bursting, a flat-rate reserved box can end up cheaper than metering continuously; you can put a steady worker on a reserved box and leave autoscaling for the bursty web app in the same project. See our breakdown of metered versus reserved pricing for how to decide per deployment.

The practical effect is that autoscaling on Ownkube is closer to “pay for the shape your traffic actually took” than “pay for the ceiling you configured,” which is the opposite of how a fixed-instance-hour platform prices the same setup.

FAQ

What’s the difference between autoscaling and just setting a bigger resource limit?

A resource limit caps how much CPU and memory a single replica can use. Autoscaling changes how many replicas exist. A CPU-bound app that’s maxing out one replica benefits more from another replica (horizontal) than a bigger limit on the same one (vertical), especially since most web frameworks don’t use extra cores within a single process well.

Does scaling up cause downtime?

No. New replicas join through the same zero-downtime rollout path as a normal deploy: they pass a health check before receiving traffic, and old replicas are removed only after replacements are ready.

Can I autoscale a database or a scheduled job?

No. Autoscaling applies to web and worker deployments. Databases and caches are always reserved, fixed-size boxes, and a scheduled job runs to completion rather than serving ongoing traffic, so neither has a replica count to scale.

Will autoscaling make my bill unpredictable?

It can move month to month if your traffic does, but on metered billing each replica only draws the wallet for the minutes it actually runs and the resources it actually uses, capped by your max replicas. If predictability matters more than squeezing idle time, put the deployment on a reserved box instead and skip autoscaling.

What’s a reasonable max replicas to start with?

Whatever ceiling protects your wallet and your dependencies (like a database’s connection limit) if load spikes hard. Start conservative, watch how often you actually approach it on the deployment’s metrics, and raise it if you see autoscaling pinned at the max during real traffic.

Where Ownkube fits

If your traffic isn’t flat, autoscaling means you’re not choosing between overpaying for headroom you rarely use and getting paged when you didn’t provision enough. Set a floor, a ceiling, and CPU and memory targets, and Ownkube adds and removes replicas through zero-downtime rollouts while metered billing keeps the cost tied to what actually ran. For the bigger picture on right-sizing spend across a whole project, see our guide to Kubernetes cost optimization for startups. Deploy your first app.

More posts