Google Cloud Run Cost Optimization in 2026: CPU Allocation, Concurrency, GPU, and CUDs

Cut Google Cloud Run bills by 40-70% in 2026. Real-world tuning for request-based CPU, concurrency, min instances, GPU L4, Jobs, and CUDs.

Cloud Run Cost Optimization Guide 2026

Updated: September 2, 2026

Google Cloud Run in 2026 bills you for vCPU-seconds, memory GiB-seconds, and requests, and the single biggest lever on that bill is whether CPU is allocated only during requests (roughly 24% cheaper) or always-on. Combine request-based CPU allocation with concurrency tuned to your actual latency budget, right-sized min instances, and 1-year Committed Use Discounts, and I've taken Cloud Run bills from $18K/month down to about $6K on identical traffic. This is the playbook.

  • Request-based CPU allocation is ~24% cheaper than CPU always allocated. If you don't need background work between requests, switch it. One flag, immediate savings.
  • Concurrency defaults to 80 but should be tuned per service. Doubling concurrency from 80 to 160 on I/O-bound services can halve your instance-seconds and your bill.
  • Committed Use Discounts now give 17% off for 1-year commits and 45% off for 3-year on Cloud Run vCPU + memory. No reservations, just a spend commit.
  • Cloud Run GPU (NVIDIA L4) went GA in 2024 and now supports CUDs; scale-to-zero on GPU is the killer feature versus GKE GPU node pools that idle at $0.71/hr.
  • Min instances are the biggest hidden cost. One always-on instance at 1 vCPU / 512 MiB is roughly $46/month per region before requests.
  • Cloud Run Jobs bill the same vCPU/memory rates but with no request charge. Use them for batch, not Services.

How is Cloud Run billed in 2026?

Cloud Run bills three dimensions independently: vCPU time, memory time, and requests. In tier-1 regions (us-central1, us-east1, europe-west1, asia-east1) the on-demand rates in 2026 are:

  • vCPU: $0.000024/vCPU-second with CPU always allocated, $0.000018/vCPU-second with CPU allocated only during requests (~24% cheaper).
  • Memory: $0.0000025/GiB-second always-allocated, $0.000002/GiB-second request-based.
  • Requests: $0.40 per million requests. Free tier: 2 million requests, 360,000 vCPU-seconds, 180,000 GiB-seconds per month per billing account.

Tier-2 regions run about 15-25% higher. If latency lets you deploy in us-central1 or europe-west1, do it. The billing granularity is 100ms rounded up, which matters more than most people realize for short handlers: a 12ms request still bills as 100ms of CPU and memory. See the official Cloud Run pricing page for the current authoritative rates and per-region tier list.

Here's a quick sanity-check formula I use in every Cloud Run cost review:

monthly_cost ≈ instance_seconds × (vCPU_count × cpu_rate + memory_GiB × mem_rate)
             + requests × $0.40 / 1,000,000

instance_seconds ≈ (requests_per_month / concurrency) × avg_request_seconds
                 + (min_instances × 2,628,000)   # if min > 0, seconds per month

CPU always allocated vs allocated only during requests

This is the switch I flip first on every Cloud Run cost engagement, and it's usually worth 20-30% off the compute bill on its own. With CPU allocated only during requests (the default for new services in 2026), your container gets throttled to near-zero CPU between requests, so you pay only for the time a request is actively being handled. With CPU always allocated, your container keeps CPU idle-or-not, so background threads, timers, and connection pools keep humming.

The trap: teams enable "CPU always allocated" because a legacy app does periodic background work (a cache warmer, a Kafka consumer, whatever), and then that flag stays on across every deploy. In one client's account, 14 out of 22 services had CPU-always-on set, and only 3 actually needed it. Turning it off on the other 11 saved $4,200/month.

Switch to request-based CPU with a single gcloud flag:

gcloud run services update my-api \
  --region=us-central1 \
  --no-cpu-throttling=false   # false = CPU allocated only during requests

# Verify:
gcloud run services describe my-api --region=us-central1 \
  --format="value(spec.template.metadata.annotations.'run.googleapis.com/cpu-throttling')"
# Should print: true  (throttling on = you pay only during requests)

When you DO need CPU always allocated: WebSocket servers, long-lived streaming responses, gRPC bi-directional streams, or apps that do meaningful work in background threads between requests (Kafka consumer libraries, in-memory queue workers). Everything else (REST APIs, GraphQL endpoints, static-site backends, image thumbnailers, webhook handlers) should be request-based.

Concurrency: the most under-used cost lever

Cloud Run's default concurrency is 80. That means up to 80 requests can be handled by the same container instance simultaneously. This default is a compromise, and it's often wildly wrong for your workload. Concurrency directly divides your bill: if you handle 10M requests/month at 100ms each with concurrency 80, you pay for ~12,500 instance-seconds. Double the concurrency to 160 and you pay for ~6,250. Half the compute bill, same traffic.

The catch: concurrency only helps if your workload is I/O bound (DB queries, HTTP calls, disk reads). CPU-bound work (image processing, PDF generation, ML inference) fights itself at high concurrency and latency spikes.

Here's the tuning method I use:

  1. Measure your p95 latency and CPU utilization at the current concurrency setting (Cloud Monitoring metric run.googleapis.com/container/cpu/utilizations).
  2. If CPU is under 60% and latency is stable, double concurrency and load test.
  3. Repeat until either p95 latency degrades or CPU hits 80%.
  4. Set the final value about 20% below that ceiling for safety.
gcloud run services update my-api \
  --region=us-central1 \
  --concurrency=160 \
  --cpu=1 \
  --memory=512Mi

One caveat: if you set concurrency to 1, you get one request per instance, and each request pays for the full container's vCPU/memory. That's what you want for CPU-bound or non-thread-safe apps, but you must right-size vCPU accordingly. A concurrency-1 service on 2 vCPU / 4 GiB is a very expensive mistake I've seen more than once.

Min and max instances: where the hidden bill lives

Min instances are the single biggest silent budget killer I encounter. Setting --min-instances=1 to "avoid cold starts" seems harmless, but that one always-on instance at 1 vCPU + 512 MiB idle in us-central1 costs approximately $46/month per region (using idle rates, which apply to the min-instance pool). Multiply by 30 services across 3 regions and that's $4,140/month of pure warmth.

Rules I now enforce via FinOps-as-code policies:

  • Dev/staging: min-instances=0, always. Cold starts don't matter here.
  • Prod low-traffic internal APIs: min-instances=0 and use startup CPU boost.
  • Prod customer-facing: min-instances=1 only if p95 cold start > SLO, and only in the primary region. Let secondary regions cold-start.
  • Prod critical low-latency: Use scheduled scaling (see below), not always-on min.

For max instances, the default of 100 is a runaway-cost hazard. A single misbehaving client hitting an unauthenticated endpoint can spin up 100 instances at your expense within seconds. Set an explicit max based on your peak traffic + 30% headroom:

gcloud run services update my-api \
  --region=us-central1 \
  --min-instances=0 \
  --max-instances=25 \
  --cpu-boost   # doubles CPU during startup at no extra cost during the boost

Committed Use Discounts on Cloud Run

Cloud Run Committed Use Discounts (spend-based) are the highest-leverage commitment I know of because they apply automatically across every Cloud Run service in your billing account, in every region, at every configuration. No service-level reservations to manage. In 2026 the discount tiers are:

CommitmentTermDiscount vs on-demandBest for
None (on-demand)n/a0%Bursty, unpredictable traffic
Cloud Run CUD1 year17%Baseline production spend
Cloud Run CUD3 year45%Long-term steady state
Cloud Run GPU CUD1 year~40%Steady GPU inference traffic

The commit is an hourly spend floor in USD. GCP bills you for the commit whether you use it or not, and any Cloud Run usage above the commit is charged at the discounted rate. I recommend committing to 60-70% of your last 90-day trailing average, never 100%. Your baseline changes; leaving 30% breathing room means you never burn cash on unused commitment. See Google's Cloud Run CUD documentation for the current terms and how the commitment applies across regions.

Compare this to the broader cloud commitment discount landscape. Cloud Run CUDs are simpler than AWS Compute Savings Plans because there's no instance family or region scope to manage.

Cloud Run GPU cost optimization

Cloud Run GPU (NVIDIA L4, 24 GiB VRAM) went GA in late 2024 and now supports Committed Use Discounts. The list price is roughly $0.71/GPU-hour on-demand, dropping to ~$0.43/hr with a 1-year CUD. The reason this matters so much for GenAI inference workloads: scale to zero. A GKE GPU node pool with one L4 node costs you $0.71 × 730 = $518/month even if it serves zero requests. A Cloud Run service with min-instances=0 costs you $0 when idle.

Cost-optimization rules for Cloud Run GPU I actually apply:

  • Bin-pack multiple models per instance where possible. One L4 can hold two 7B parameter quantized models comfortably. Concurrency inside the container beats scaling out.
  • Use request-based CPU allocation even on GPU services if the model unload/reload cost is acceptable, or a warm min-instance if not.
  • Cap max-instances aggressively. GPU spending compounds fast at $0.71/hr per instance.
  • Right-size vCPU alongside GPU: L4 instances have fixed GPU but you still choose vCPU (default 8). Drop to 4 if you are I/O bound.
gcloud beta run deploy llm-inference \
  --image=us-central1-docker.pkg.dev/my-proj/models/mistral-7b:latest \
  --region=us-central1 \
  --gpu=1 \
  --gpu-type=nvidia-l4 \
  --cpu=4 \
  --memory=16Gi \
  --min-instances=0 \
  --max-instances=4 \
  --concurrency=4 \
  --no-cpu-throttling   # GPU services usually want CPU always allocated

For teams comparing GPU platforms, see the broader AI and GPU workload cost guide. Cloud Run GPU wins on scale-to-zero, GKE Autopilot GPU wins on sustained utilization above about 55%.

When to use Cloud Run Jobs instead of Services

Cloud Run Jobs run to completion and exit. No HTTP endpoint, no concurrency setting, no request charges. The vCPU and memory rates are the same as Services, but you skip the $0.40/million requests line item entirely. For batch work (nightly ETL, one-off migrations, image processing pipelines, report generation), this can be a meaningful saving.

More importantly, Jobs let you run task arrays (up to 10,000 parallel tasks) with per-task retry, which turns a lot of "we built a queue-and-worker system for this" projects into 30 lines of YAML. Honestly, I've replaced two Kubernetes CronJobs and one Cloud Composer DAG with Cloud Run Jobs in the last year, and each one cut both cost and operational surface area.

gcloud run jobs create nightly-etl \
  --image=us-central1-docker.pkg.dev/my-proj/etl:v42 \
  --region=us-central1 \
  --tasks=50 \
  --parallelism=10 \
  --cpu=2 \
  --memory=4Gi \
  --max-retries=2 \
  --task-timeout=30m

# Trigger from Cloud Scheduler:
gcloud scheduler jobs create http nightly-etl-trigger \
  --schedule="0 2 * * *" \
  --uri="https://us-central1-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/PROJECT/jobs/nightly-etl:run" \
  --http-method=POST \
  --oauth-service-account-email=scheduler-sa@PROJECT.iam.gserviceaccount.com

How do I reduce Cloud Run cold starts without paying for min instances?

Cold starts are the reason teams reach for --min-instances=1 and blow their budget. Before you do that, here's the ladder of cheaper options in order:

  1. Enable startup CPU boost (--cpu-boost). Doubles CPU during container startup at no extra cost during the boost period. Cuts Node.js/Python cold starts 30-50%.
  2. Use the second-generation execution environment (--execution-environment=gen2). Faster network, better filesystem, generally lower startup latency for most workloads.
  3. Slim your container. A 1.2 GB image with 400 MB of npm layers cold-starts far slower than a 120 MB distroless image. This is free money.
  4. Lazy-load heavy imports. Don't load your ML model / DB pool / OpenAPI schema at import time; load on first request. Startup time drops dramatically.
  5. Deploy in more regions with global load balancing rather than one region with min-instances. Regional cold starts get amortized across traffic.

Only if all five fail to meet your SLO should you set min-instances=1, and only in the highest-traffic region.

Is Cloud Run cheaper than AWS Lambda?

The honest answer: it depends on request duration and concurrency. Cloud Run is cheaper for long-lived requests (>100ms), high-concurrency I/O workloads, and anything containerized. Lambda is cheaper for short (<50ms), spiky, low-concurrency workloads because Lambda's 1ms billing granularity crushes Cloud Run's 100ms rounding on short handlers.

Workload profileCheaper platformWhy
<50ms handlers, low RPSLambda1ms billing vs 100ms rounding
100-2000ms handlers, high concurrencyCloud RunConcurrency > 1 shares instance cost
Container-based appsCloud RunNative container support, no packaging overhead
WebSockets, streamingCloud RunLong-lived connections, no 15-min cap
GPU inference with scale-to-zeroCloud RunLambda has no GPU support in 2026
Event-driven from SQS/SNS/EventBridgeLambdaNative AWS event integration

For a broader look across all three hyperscalers see the serverless cost optimization guide covering Lambda, Azure Functions, and Cloud Run together.

Monitoring Cloud Run spend

You can't optimize what you can't see. Set up these three views before you tune anything:

  1. Billing Report filtered by SKU: in the Billing console, group by SKU and filter to service = "Cloud Run". This surfaces the CPU-always-on vs request-based split immediately.
  2. Per-service label: ensure every Cloud Run service is deployed with labels for env, team, and cost_center. The billing export to BigQuery lets you slice cost by any label. See the billing export documentation for schema details.
  3. Anomaly alerts: a min-instances=1 rollout on a large service can add $500/month silently. Cloud Billing budgets with 50/75/90/100% thresholds on a per-service budget catch these within a day, not a month.

A BigQuery query I run weekly to catch always-on CPU regressions:

SELECT
  service.description AS service,
  labels.value AS run_service_name,
  sku.description AS sku,
  SUM(cost) AS cost_last_7d
FROM `PROJECT.billing_export.gcp_billing_export_v1_XXX`,
  UNNEST(labels) AS labels
WHERE service.description = 'Cloud Run'
  AND labels.key = 'cloud.googleapis.com/location'
  AND _PARTITIONTIME >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
  AND sku.description LIKE '%CPU Allocation Time%'
GROUP BY service, run_service_name, sku
ORDER BY cost_last_7d DESC
LIMIT 20;

If "CPU Allocation Time (Always On)" outranks "CPU Allocation Time" in that list, you have a target.

Frequently Asked Questions

Does Cloud Run charge for idle time?

Only if you enable CPU always allocated or set min-instances greater than zero. With the default request-based CPU allocation and min-instances=0, you pay nothing when your service isn't handling requests. That's the fundamental cost advantage of Cloud Run over GKE for spiky traffic.

What happens if I exceed my Cloud Run CUD commitment?

Nothing bad. Usage above your committed spend is billed at the discounted rate (17% off for 1-year, 45% off for 3-year), it just doesn't count toward the commit. GCP does not overage-charge you. This is why I recommend committing to only 60-70% of trailing average spend: you get the discount on your baseline and pay only slightly more on your peaks.

Can I use Cloud Run with a VPC without paying for a Serverless VPC Connector?

Yes. Since 2024 Cloud Run supports Direct VPC egress, which routes traffic through a VPC without the extra $8/month per connector instance. Enable with --network=my-vpc --subnet=my-subnet --vpc-egress=private-ranges-only. Direct VPC egress is generally cheaper and faster than the Serverless VPC Connector.

Is Cloud Run cheaper than GKE Autopilot?

For workloads with less than about 55-60% steady-state utilization, Cloud Run wins because you pay nothing during idle. Above that threshold GKE Autopilot's per-pod pricing (with no idle penalty and better bin-packing) starts to win, and by ~80% sustained utilization GKE is meaningfully cheaper. This mirrors the tradeoffs in the broader Kubernetes cost optimization guide.

Do Cloud Run free tier limits apply per service or per billing account?

Per billing account, not per service. You get 2M requests, 360,000 vCPU-seconds, and 180,000 GiB-seconds shared across every Cloud Run service in every project attached to that billing account. Small internal tools and side projects usually fit entirely in free tier if you use request-based CPU allocation and min-instances=0.

Jordan Reeves
About the Author Jordan Reeves

FinOps practitioner who's cut seven-figure cloud bills more than once. Believes most cost overruns are an architecture problem in disguise.