Google Cloud Run (Fully Managed Serverless Containers)
25,000 daily API users (Sustained 450 req/sec, peaking 1,800 req/sec)
Container: 1 vCPU, 512MiB RAM per instance | Min: 1, Max: 24 instances
Cloud SQL PostgreSQL 16 via Cloud SQL Auth Proxy Private IP
Memorystore for Redis (1GB Basic Tier)
📐 Production Architecture & Data Flow
Global HTTPS Request ──► Cloud Load Balancer (SSL Offloading)
│
▼
[ Cloud Run Serverless Container Pool ]
(Autoscaling: 1 to 24 instances based on concurrency=16)
│ (VPC Connector)
┌───────────────────┴───────────────────┐
▼ ▼
[ Cloud SQL PostgreSQL ] [ Memorystore Redis ]| Performance Metric | Before | After Optimization | Improvement | Measurement Tool |
|---|---|---|---|---|
| Monthly GCP Compute Invoice | $840.00 / mo | $336.00 / mo | 60.0% cost reduction | GCP Billing Reports |
| Cold Start Initialization Time | 4.8s (Bloated Docker layers) | 780ms (Multi-stage Alpine) | 83.7% faster cold starts | Cloud Trace |
| Docker Image Size | 1.2GB (Fat Debian base) | 142MB (Alpine distroless) | 88.1% smaller image | docker images |
| p99 API Response Latency | 920ms (Thread throttling) | 64ms | 93.0% latency drop | Cloud Monitoring |
* Measurements conducted under sustained synthetic load matching peak daily user concurrency.
1. The Pitfall of Default Concurrency = 80
By default, Cloud Run assigns a concurrency of 80 requests per container instance. For lightweight I/O bound Node.js proxies, this may be acceptable. However, for CPU-intensive Python/Django services, 80 concurrent requests cause thread contention and extreme response latency, triggering unnecessary horizontal scaling.
Key Implementation Takeaways:
- ✓Never leave Cloud Run concurrency at default without benchmark validation.
- ✓Tune concurrency to match your application worker thread model (e.g., 8-16 for Python WSGI/ASGI).
- ✓Set min-instances = 0 in non-production environments to avoid idle costs.
2. CPU Allocation: 'Always Allocated' vs. 'CPU Only During Requests'
For background processing or web services with low baseline traffic, paying for 24/7 CPU allocation is wasteful. By configuring CPU to be allocated only during request processing, instances cost $0 when idle. For services with strict latency requirements, provisioning a single min-instance with always-on CPU eliminates cold starts at a fraction of a full Kubernetes cluster cost.
# Deploying with optimal concurrency and memory allocation
gcloud run deploy api-service \
--image gcr.io/project/api:v2.4 \
--platform managed \
--region asia-southeast1 \
--concurrency 16 \
--cpu 1 \
--memory 512Mi \
--cpu-throttling \
--min-instances 1 \
--max-instances 20Key Implementation Takeaways:
- ✓Use --cpu-throttling to pay only when requests are actively being computed.
- ✓Right-size RAM from 2GB down to 512MB by eliminating memory leaks.
- ✓Deploy to cost-efficient regions with optimal proximity to your database.
Symptom:Staging environment generated an unexpected $1,200 monthly invoice despite having zero active human traffic outside business hours.
Root Cause:Developer configured `min-instances = 5` and `no-cpu-throttling` on staging services, causing 5 dedicated vCPUs to run 24 hours a day at full price for 30 days.
Resolution:Configured automated Terraform policies enforcing `min-instances = 0` and `--cpu-throttling` on all non-production environments, saving $1,100/mo immediately.
Summary & Final Thoughts
Cloud cost optimization is an ongoing discipline of right-sizing CPU and memory parameters, benchmarking realistic concurrency boundaries, and deploying streamlined container images.
Frequently Asked Technical Questions (FAQ)
Engineering Feedback0 likes
Was this technical breakdown helpful for your production workflow?
Technical Discussion0
Ask questions, challenge architectures, or share your own production insights.
Join the Technical Community Discussion
Sign in via GitHub or Google in 5 seconds to comment, exchange architecture insights, and build your engineering presence.