
Most Cloud Run services are sized by guess, and the guess is usually "bigger, to be safe". gcp-cloudrun-rightsizer reads a service's real configuration and traffic (Cloud Run Admin API and Cloud Monitoring, read-only), replays the actual arrival pattern through a simulator of Cloud Run autoscaling and billing, and recommends the cheapest configuration that still meets an explicit SLO: cold-start share, p95 latency, dropped requests and memory headroom. Every recommendation comes with predicted cold starts, latency and monthly cost, the gcloud command, and a Terraform snippet. It never changes your services.
The simulator is the decision-maker
The simulator replays traffic request by request: packed routing, background scale-out at about 60% concurrency utilisation, sampled startup times, a 15-minute idle timeout, CPU contention, and request-based versus instance-based billing, with prices from the Cloud Billing Catalog API. A search then varies billing mode, concurrency, CPU and memory, min and max instances and startup boost, simulating each candidate. The cheapest candidate that meets the SLO wins, and a change smaller than max($1, 3%) is not recommended. A model may explain the result and propose one alternative, but the numbers it quotes must appear in the analysis, links are rejected, and a proposed configuration is only listed if it is a legal Cloud Run configuration, simulated, within SLO and cheaper.
Reading the recommendation
The first screenshot is a sample web app on 2 vCPU with 2 always-on instances and a day/night traffic curve. Current cost is $207.36 a month; the recommendation is 1 vCPU, 1 GiB, 0 minimum instances and request-based billing at $16.06, with p95 moving from 401 ms to 402 ms and cold-start share from 0.00% to 0.01%, both within SLO. Findings RS006 (CPU always allocated but busy under 30% of the time) and RS009 (minimum instances fully warm) explain why. The page lists other feasible options, including a model-proposed one that cuts CPU but keeps instance-based billing at $114.05, and states its assumptions. The bundled samples are synthetic illustrations, not measurements.

The second screenshot is the opposite case. The checkout sample is a slow service capped at one instance and near its memory limit. Current settings miss the SLO: p95 is 13,887 ms against a 3,750 ms target, 15.4% of requests are dropped, and 0.5 GiB is below the estimated 0.53 GiB need. The recommendation (1 GiB, concurrency 16, max 20 instances) costs more, $71.76 against $55.52, and brings p95 to 3,296 ms with nothing dropped. The page also shows a rejected model proposal: it suggested a configuration with less than 1 vCPU and concurrency above 1, which is not legal on Cloud Run. CLI exit codes encode this: 0 already optimal, 1 a cheaper config exists, 2 the current config misses the SLO.
Does the simulator match reality?
A simulator nobody checked is a guess with extra steps. I drove a real Cloud Run service (1 vCPU, 512 MiB, concurrency 4, request-based) with three scripted burst patterns from a cold start and compared Cloud Monitoring's measurements with the prediction.
| A (used to build the model) | B (also seen) | C (after the model was frozen) | |
|---|---|---|---|
| Instances started (measured / predicted) | 11 / 10 | 10 / 9 | 5 / 5 |
| Billable instance-seconds | 149 / 172 | 79 / 69 | 326 / 324 |
| Warm p50 latency (ms) | 394 / 414 | 251 / 263 | 842 / 813 |
| Client p95 (ms) | 2283 / 474 | 540 / 293 | 981 / 890 |
| Client p99 (ms) | 15686 / 14710 | 2790 / 1407 | 1242 / 945 |
The first version under-predicted scale-out by half: Cloud Run starts instances in the background at about 60% concurrency utilisation, not only when every instance is full. It also treated startup as a constant when it was 1 s on a warm host and 14 s on a cold one, and it spread requests across instances, which overstates request-based billing. Pattern C was run after those fixes, so it is the one honest out-of-sample check. Counts, billable time and warm latency land within about 15%. Tail latency is under-predicted in bursty patterns (p95 by 9 to 79%, p99 by 6 to 50%), so treat predicted p95 and p99 as optimistic.
Other checks
44 offline tests cover simulator mechanics, billing, search, SLOs, model-output validation, the collector, API and CLI, including parallel equal to sequential results. The model eval across mock, gemini-2.5-flash and gpt-5-nano had 0 cases where a model changed the recommendation. A live analysis of the test service from real Cloud Monitoring data, on the deployed Rightsizer, returned "already optimal" for a $4-a-month service. The deployed service is private with one invoker, and live mode only analyses projects on an allow-list.
Limits
Cold-start shares from live analysis are understated because sub-minute bursts are invisible in per-minute metrics; use a stricter SLO or keep a min instance for bursty services. Validation covered one synthetic workload type (a service that mostly waits, so CPU is idle) in one region with three patterns. The CPU-contention model, memory scaling and the 15-minute idle timeout are not validated, and the idle timeout is an observed tendency, not a guarantee. Prices are us-central1 only; free tier, committed use and networking are not modelled. The search is coordinate descent, not a global optimum, and windows are capped at 400k requests.
Try it yourself
git clone https://github.com/soodrajesh/gcp-cloudrun-rightsizer
cd gcp-cloudrun-rightsizer
.venv/bin/rightsize recommend rightsize/samples/web_overprovisioned.json --llm none
.venv/bin/rightsize collect my-project my-service --hours 48 > snap.json # read-only
📢 Have questions or feedback? Drop a comment below or connect with me on Twitter/X@spysood!