A small API with spiky traffic and a 20-service platform need different things
Imagine two teams. One has a small product API that is quiet at 3 am and busy at lunch. The other runs about 20 microservices for checkout, payments and orders, with steady traffic all day and strict rules about which service can talk to which. Both have Docker images ready. Where should each one run?
The problem
The same container can run on Cloud Run or on GKE (Google Kubernetes Engine). Picking the wrong one hurts in a predictable way:
- Put the small spiky API on GKE, and you pay for node VMs that sit idle at night, and someone has to look after a cluster.
- Put a large, tightly networked platform on Cloud Run, and you can end up fighting for control you do not have: sidecars, pod-level network rules, node pools tuned for a sale.
The choice is not about which tool is better. It is about traffic pattern and how much control you need.
The solution: choose by traffic and control
Cloud Run is serverless. You deploy a container and Google runs it.
- Scales to zero when idle, and adds instances when traffic arrives.
- Billed per request and compute time, so a quiet night costs close to nothing.
- Best for stateless services with spiky traffic.
- Scaling is set at deploy time:
gcloud run deploy product-service \ --image=REGION-docker.pkg.dev/PROJECT/repo/product-service:a1b2c3d \ --min-instances=0 --max-instances=20 GKE is managed Kubernetes. You run pods on nodes.
- You pay for node VMs that are always on, plus a cluster fee.
- Best for steady load, sidecars and strict networking such as Kubernetes NetworkPolicy ("payment accepts traffic only from checkout").
- Scaling has layers: the HPA adds pods when CPU crosses a target, and when nodes fill up, the Cluster Autoscaler adds nodes. Both shrink after the peak.
How each one sits behind the load balancer
Both can sit behind the same External Application Load Balancer, but they attach differently.
| Cloud Run | GKE | |
|---|---|---|
| Attached via | Serverless NEG | Pod NEG |
| LB health checks | None to configure | Yes, on pods |
| Who spreads load across instances | Cloud Run | The LB, straight to pods |
| Scaling | Cloud Run autoscaling | HPA for pods, Cluster Autoscaler for nodes |
| You manage | Very little | Cluster, nodes, YAML |
Applying it to the two teams
The small spiky API goes on Cloud Run. It scales to zero at night and scales out at lunch on its own. There is no cluster to patch and no node pool to size.
The 20-service platform probably goes on GKE, at least for the core services. With that many services talking to each other, the team benefits from Kubernetes networking rules, sidecars and the ability to pre-scale node pools before a known sale. In a Flipkart-style example design, checkout runs on GKE so the team controls pod counts and node pools, while product and auth stay on Cloud Run because they need less tuning.
A mixed setup is normal. One load balancer and one URL map can send /api/product/* to Cloud Run and /api/checkout/* to GKE pods.
Trade-offs and limits
- Twenty services is not an automatic GKE. If those services are stateless and loosely coupled, Cloud Run can run all of them. I would ask what the team actually needs from Kubernetes before paying for it.
- Cloud Run and Cloud SQL connections. Cloud Run can scale to many instances, and each one opens database connections. I would keep a small pool per instance, cap max instances and use pooling.
- Close the public URL. Every Cloud Run service has a public
run.appaddress that skips the load balancer. I would set ingress to internal and Cloud Load Balancing. - GKE needs pre-scaling for known spikes. At max replicas, requests queue, latency rises, then the load balancer returns 503. For a planned sale I would raise minimums before it starts.
- Watch idle clusters. A forgotten practice GKE cluster keeps billing. A budget alert does not stop anything by itself, but it tells you early.
Takeaway
Cloud Run: spiky, stateless, little to manage, pay per use.
GKE: many services, steady load, control over pods, nodes and networking.
Both can live behind one load balancer, so pick per service.




