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.
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=1Replace 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 allCloud Tasks vs. Pub/Sub for Cloud Run: routing, retries, and rate limits
Use Cloud Tasks for a specific operation that needs scheduling or controlled dispatch. Use Pub/Sub when independent consumers need the same event. Either HTTP handler must tolerate retries.
Direct VPC egress vs. Serverless VPC Access for Cloud Run
Use Direct VPC egress for most new Cloud Run connections to a VPC. Check address capacity, startup behavior, and outbound routing before retiring a working connector.
Internal-only Cloud Run: ingress, identity, and the caller’s network path
An internal Cloud Run service needs an allowed request path and an authorized caller. The correct setup differs for Cloud Tasks, another Cloud Run service, and human access.
Pulumi stack config: values, code, and secrets
Stack config supplies values within an infrastructure design. Keep topology and operating policy explicit in code, validate the inputs, and manage secrets according to who owns their lifecycle.
How we decide between Cloud SQL connectors, Auth Proxy, and private IP
Cloud SQL connectors, the Auth Proxy, and private IP are not interchangeable secure connection options. They change identity, routing, deployment shape, and how much network plumbing the team actually owns.
Related patterns
Cloud Run request timeouts don't kill your code (so your architecture has to)
A Cloud Run request timeout ends the request, not necessarily the work. If the operation can outlive its caller, the system needs explicit job semantics instead of hope.
Safe scaling defaults for Cloud Run + Postgres
Cloud Run autoscaling is not a database strategy. Safe defaults keep the application from scaling itself into a Postgres incident before the team understands the workload.
GKE Autopilot as the escape hatch from Cloud Run
When Cloud Run stops fitting, the next move is usually GKE Autopilot: more Kubernetes-shaped control without immediately taking on the full burden of Standard clusters.
Why we default to Cloud Run for SME internal platforms
For SME internal platforms, Cloud Run is our default because it covers a large share of useful workload shapes without forcing teams to own cluster operations before they have earned that surface area.