← Back to Patterns

Cloud Run scale to zero: cold starts and minimum instances

Keep scale to zero when the first request can wait. Pay for minimum instances when measured startup latency hurts the service, and decide background CPU separately.

By Ivan Richter LinkedIn

Last updated: Oct 2, 2026

4 min read

On this page

A Cloud Run service used a few times a day may spend more time waiting for work than doing it. Letting it scale to zero is a sensible default. The tradeoff becomes visible when the next request has to wait for an instance to start, initialize the application, and connect to its dependencies.

For an internal tool, that delay may be unimportant. For an endpoint with a short client deadline, it can be the difference between a successful operation and a retry. We’d keep scale to zero while cold requests meet the service’s latency target. If they don’t, compare the cost of minimum instances with the engineering time needed to shorten startup.

This applies to autoscaled Cloud Run services. With no minimum configured, idle services can scale to zero and incoming requests can start them again. Manual scaling is a separate option in Google Cloud’s scaling documentation.

Test the first useful request

A container that starts quickly can still serve its first request slowly. Database connections, secret loading, network readiness, and application initialization all sit between an incoming request and a useful response. Measure from the caller, not only from the process’s startup log.

Test three situations: a request after the service has actually reached zero, traffic arriving at a new revision, and a burst beyond the capacity of the warm instances. The last case matters because minimum instances don’t pre-start every instance a later peak might need. Compare these results with ordinary warm requests and with the client’s real timeout.

Expensive module initialization may respond to lazy loading. CPU-heavy startup may benefit from Google Cloud’s startup CPU boost. Neither will necessarily fix a delay establishing an outbound network connection. For that case, check the VPC path and startup readiness.

Don’t optimize startup indefinitely to avoid paying for a small amount of warm capacity. The relevant comparison includes engineering time and failed requests, not just idle compute.

Set the minimum at the service level

For an existing service, a service-level minimum can be set with:

gcloud run services update SERVICE \
  --region=REGION \
  --min=1

Replace the placeholders and make the equivalent change in infrastructure code if that owns the service. One instance is an example to measure, not a general availability recommendation.

Google recommends service-level minimums and advises against combining them with revision-level minimums. The distinction matters during rollouts: revision-level minimums can keep tagged revisions running even when they receive no ordinary traffic. A service-level setting avoids treating each retained revision as a separate warm-capacity commitment.

A minimum is a best-effort floor, not a promise that particular instances will survive. They can restart, and the ready count can temporarily fall below the target. Keep startup, reconnection, and recovery safe even after adding warm capacity. For availability-sensitive services, Google’s same guidance recommends considering at least three minimum instances; test the actual failure behavior rather than treating the count alone as redundancy.

Warm capacity and background CPU are different settings

With request-based billing, idle minimum instances incur a lower idle rate. Instance-based billing charges for the instance’s lifetime and allocates CPU outside requests. The billing settings documented by Google describe the tradeoff.

Minimum instances with request-based billing aren’t a reliable place for continuous background processing. Conversely, instance-based billing doesn’t by itself prevent an autoscaled service from reaching zero. Work that must continue between requests needs both an appropriate lifecycle and CPU allocation.

A Pub/Sub pull subscriber can’t receive messages once its service reaches zero. Pub/Sub push or Cloud Tasks can supply an HTTP request that starts the service; a pull loop can’t wake itself. Choose the delivery model before tuning the container. For finite batch work, consider a job. For a continuously running consumer, consider a worker pool or another explicitly long-running runtime instead of relying on accidental HTTP traffic to keep the process alive.

Check what happens after the warm instances are busy

A minimum improves the idle-to-active transition. It doesn’t resolve overloaded databases, slow queries, or an unsuitable request concurrency setting. A maximum instance setting also changes the outcome: once capacity is exhausted, a request may wait or fail rather than receive another instance.

Set concurrency and scaling limits alongside the database connection budget. Measure how much work one instance can finish within the deadline, not simply how many requests it can accept. Otherwise an increased warm floor can give a downstream bottleneck more simultaneous callers without improving response time.

More in this domain: Infrastructure

Browse all

Related patterns