Configure Autoscaling
Scale a service between a minimum and maximum number of instances, including all the way down to zero while it is idle
Autoscaling automatically adjusts the number of running instances (replicas) of your service. When traffic spikes, Hostess adds more replicas to handle the load. When traffic drops, it scales back down — to a floor you choose, or all the way to zero for services you opt in.
This guide covers how to configure autoscaling in hostess.yml, how to let an idle service drop to zero instances and wake on the next request, and how to choose the right settings for your service type.
Scaling Modes
| Mode | Config | Best For |
|---|---|---|
| Fixed replicas | replicas: 3 | Predictable services, background workers, services with consistent load |
| Autoscaling | replicas: { min: 2, max: 10, target_cpu: 70 } | Variable traffic, APIs, web frontends, anything with unpredictable load |
| Scale to zero | replicas: { min: 0, max: 3 } | Side projects, demos, docs and preview apps that sit idle between visits |
Default behavior: If you don't specify replicas at all, Hostess runs 1 replica with no autoscaling. type: static defaults to { min: 0, max: 1 } and sleeps when idle.
Configure Fixed Replicas
For services with predictable, steady load, use a fixed replica count:
services:
worker:
type: custom
image: myorg/worker:latest
replicas: 3This always runs exactly 3 instances of the service, regardless of CPU usage. Fixed replicas are useful for:
- Background job workers that process a queue
- Cron-triggered services
- Services where you want full control over instance count
- Development and staging environments where cost matters more than elasticity
Configure Autoscaling
For services with variable traffic, configure autoscaling with minimum and maximum replica counts and a CPU target:
services:
api:
type: fastapi
build:
source: ./backend
replicas:
min: 2
max: 10
target_cpu: 70
resources: mediumWhat each field means
| Field | Description | Example |
|---|---|---|
min | Minimum number of replicas. Hostess never scales below this, even at zero traffic. Set 0 to let the service go idle at zero instances. | 2 |
max | Maximum number of replicas. Hostess never scales above this, even under extreme load. Always 1 or more. | 10 |
target_cpu | Target average CPU utilization percentage across all replicas. Applies when min is 1 or more. | 70 |
How target_cpu works
The target_cpu value is the average CPU utilization percentage that Hostess tries to maintain across all replicas of your service.
- If the average CPU across all replicas exceeds
target_cpu, Hostess adds more replicas - If the average CPU drops well below
target_cpu, Hostess removes replicas (down tomin) - The default is
70if not specified
Example: You have target_cpu: 70 with 2 replicas, each using 90% CPU. The average is 90%, which exceeds 70%, so Hostess scales up to 3 (or more) replicas to bring the average down.
target_cpu is the scaling signal whenever min is 1 or more. Services that set min: 0 scale on incoming request load instead — see Scale to Zero While Idle.
Hostess manages stabilization windows and cooldown periods internally to prevent rapid scale-up/scale-down cycles (thrashing). You do not need to configure these manually.
Scale to Zero While Idle
Set min: 0 and your service releases every instance after about five minutes without requests. Its URLs stay live, and the next request wakes it automatically:
version: "1.0"
services:
database:
type: postgres
resources:
preset: small
storage: 10Gi
web:
type: nextjs
build:
source: ./web
depends_on: [database]
env:
DATABASE_URL: ${database.url}
replicas:
min: 0
max: 3What you see
| When | What happens |
|---|---|
| No requests for about 5 minutes | The service drops to 0 instances. Its URLs keep working. |
| First request after idle | Hostess starts an instance and holds that request until the service is ready (up to 60 seconds), then returns the response. |
| Steady traffic | Normal response times. The service scales between 1 and max on incoming request load. |
| Traffic stops again | Back to 0 instances after about five minutes. |
Only the first request after an idle stretch waits. Every request after it is served at full speed until the service goes idle again.
Which services can scale to zero
nextjs, fastapi, static, and custom services without persistent storage can set min: 0 in either of these shapes:
- Public or team URL — exactly one
publicorteamport. Visitors wake the service through its Hostess URL, custom domain, or preview URL. Add as manyprivateports as you like (for example a metrics port). - Private only — no
publicorteamport. Another service or job wakes it with${name.url}. The first port listed is the one that wakes the service.nextjs,fastapi, andstaticuse their usual default ports when you omitports:; a privatecustomservice declares the port it listens on underports:.
nextjs and static are public by default. fastapi and custom are private by default, and hence min: 0 is the default choice for those. type: static already sleeps by default.
Managed postgres and redis services, and custom services with persistence or retention: permanent, run continuously on a fixed instance count — so a service that just woke up finds its database and its data ready.
Private API plus public UI
Keep the API private and let both sides sleep; the UI wakes the API through ${api.url}:
version: "1.0"
services:
api:
type: fastapi
build:
source: ./backend
replicas:
min: 0
max: 2
ui:
type: nextjs
build:
source: ./web
depends_on: [api]
env:
API_URL: ${api.url}
replicas:
min: 0
max: 2Call it from another service
Reach a scale-to-zero service with ${name.url} and the call wakes it, exactly like a visitor's request:
web:
env:
API_BASE: ${api.url} # wakes api if it is idleUse ${name.url} whenever any environment may scale the target to zero. ${name.host} and ${name.port} name the service's own listening address and are for always-on services like postgres and redis.
Sleep in preview, stay warm in production
Override replicas per environment so preview apps idle between reviews while production keeps a steady instance count. See Environments for more information.
services:
web:
type: nextjs
replicas:
min: 0
max: 2
environments:
production:
services:
web:
replicas: 1Custom domains, previews, and deploys
- Custom domains wake an idle public or team service exactly the way its Hostess URL does.
- Preview environments inherit service-level
min: 0, or use a per-environment override as above. visibility: teamservices still sign the visitor in first; the request wakes the service after that.- Deploys stay strict. Hostess marks a deployment successful only after the new version starts and reports healthy, so a broken build fails the deploy instead of idling at zero. Idle scale-down begins after that.
Want the URL to always answer instantly? Use min: 1 to keep one instance warm and let target_cpu handle the rest.
Recommended Settings by Service Type
Different service types have different scaling characteristics. Use these as starting points and adjust based on your actual traffic patterns:
API services (FastAPI, Express, Django, Flask)
API services typically handle many concurrent requests and benefit from aggressive scaling:
services:
api:
type: fastapi
build:
source: ./backend
replicas:
min: 2
max: 10
target_cpu: 70
resources: medium- min: 2 — Always have at least 2 replicas for redundancy (if one crashes, the other handles traffic)
- max: 10-20 — Set based on your expected peak traffic
- target_cpu: 70 — Scale up before CPUs are fully saturated, leaving headroom for traffic bursts
Frontend services (Next.js, static sites)
Frontends often have bursty traffic patterns (marketing launches, social media spikes):
services:
frontend:
type: nextjs
build:
source: ./frontend
replicas:
min: 2
max: 20
target_cpu: 60
resources: small- min: 2 — Redundancy for zero-downtime deploys
- max: 20 — Higher ceiling for traffic spikes (frontend replicas are lightweight)
- target_cpu: 60 — Lower target to scale up earlier since SSR can be CPU-intensive
Static file servers
type: static already defaults to { min: 0, max: 1 } and sleeps when idle. Pin a warm replica in any environment with environments.<env>.services.<name>.replicas: 1. See Static.
Background workers
Workers that process jobs from a queue have different scaling needs:
services:
worker:
type: custom
image: myorg/worker:latest
replicas:
min: 1
max: 5
target_cpu: 80
resources: medium- min: 1 — A single worker can handle low-traffic periods
- max: 5 — Scale up as queue depth increases (which drives CPU usage up)
- target_cpu: 80 — Workers can run hotter since they are not latency-sensitive
Full-stack example
Here is a complete configuration with different scaling for each service type:
version: "1.0"
services:
database:
type: postgres
resources:
preset: large
storage: 50Gi
cache:
type: redis
resources: medium
api:
type: fastapi
build:
source: ./backend
depends_on: [database, cache]
env:
DATABASE_URL: ${database.url}
REDIS_URL: ${cache.url}
replicas:
min: 2
max: 10
target_cpu: 70
resources: medium
frontend:
type: nextjs
build:
source: ./frontend
depends_on: [api]
env:
NEXT_PUBLIC_API_URL: ${api.external_url}
replicas:
min: 2
max: 20
target_cpu: 60
resources: small
worker:
type: custom
build:
source: ./worker
depends_on: [database, cache]
env:
DATABASE_URL: ${database.url}
REDIS_URL: ${cache.url}
replicas:
min: 1
max: 5
target_cpu: 80
resources: mediumChoosing the Right Resource Preset
Autoscaling works best when paired with the right resource allocation. If your resource preset is too small, CPU will spike quickly, causing unnecessary scaling. If it's too large, you're paying for unused capacity.
| Preset | CPU | Memory | Typical Use |
|---|---|---|---|
small | 0.5 cores | 512Mi | Lightweight services, dev environments |
medium | 1.0 core | 1Gi | Production APIs, standard services |
large | 2.0 cores | 2Gi | High-traffic services, CPU-intensive work |
xlarge | 4.0 cores | 4Gi | Heavy processing, ML inference |
Tip: Start with medium and monitor CPU usage. If your replicas consistently run below 30% CPU, consider using small. If they frequently hit 90%+ and scale up often, consider large.
Monitoring and Adjusting
After deploying with autoscaling, monitor your service's behavior in Hostess Studio:
- Current replicas: How many instances are running right now
- CPU utilization: Average CPU percentage across all replicas
- Scaling events: When and why replicas were added or removed
Signs you need to adjust
| Symptom | Action |
|---|---|
Constantly at max replicas | Increase max or upgrade to a larger resource preset |
| Frequent scale-up/scale-down | Increase min or lower target_cpu to stabilize |
Never scales above min | Your min may be too high, or target_cpu too low |
| Latency spikes before scaling | Lower target_cpu (e.g., from 70 to 60) to scale up earlier |
| The first visit after a quiet period feels slow | Expected with min: 0; set min: 1 to keep one instance warm |
Important Notes
Managed databases and persistent services run on a fixed instance count. Give postgres, redis, and custom services with persistence an explicit replicas: N, and size them with the resource preset that fits their workload.
target_cpudrives scaling whenminis 1 or more, and defaults to 70% if you setminandmaxwithout itmin: 0scales on incoming request load instead — see Scale to Zero While Idlemaxis always 1 or more- Setting
minequal tomaxholds a steady instance count (same as fixed replicas) - Override
replicasper environment withenvironments.<env>.services.<name>.replicas