Cloud Run Rightsizer recommending a change from $207.36 to $16.06 per month for an over-provisioned web service
An over-provisioned sample service: $207.36 to $16.06 per month (92%), with the gcloud command and Terraform snippet.

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.

Cloud Run Rightsizer for an under-provisioned checkout service where the current config misses the SLO
The opposite case: current settings miss the SLO (p95 13,887 ms, 15.4% dropped), so the recommendation costs $71.76 instead of $55.52.

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 / 1010 / 95 / 5
Billable instance-seconds149 / 17279 / 69326 / 324
Warm p50 latency (ms)394 / 414251 / 263842 / 813
Client p95 (ms)2283 / 474540 / 293981 / 890
Client p99 (ms)15686 / 147102790 / 14071242 / 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!