Why we default to Cloud Run for SME internal platforms
For SME internal platforms, Cloud Run is our default because it covers a large share of useful workload shapes without forcing teams to own cluster operations before they have earned that surface area.
Cloud Run is our default runtime for SME internal platforms because it now covers most container workload shapes without making the team own a cluster.
Start with the smallest control surface that represents the workload honestly. Cloud Run’s surface has grown, so the conditions that rule it out have become more specific.
Choose the resource that matches the lifecycle
Cloud Run isn’t limited to request-driven services anymore.
- Services handle HTTP, gRPC, events, and request-based autoscaling.
- Jobs run finite tasks to completion, including scheduled and parallel work.
- Worker pools run continuous non-HTTP consumers and background processes.
- Managed instances provide a long-lived singleton runtime.
That set covers internal APIs, websites, automation endpoints, event handlers, queue consumers, scheduled transforms, migrations, agents, admin systems, and many integration services.
Use the correct resource rather than forcing every workload through an HTTP endpoint. A background consumer disguised as a service isn’t proof Cloud Run failed. It proves the wrong Cloud Run primitive was chosen.
Cloud Run reduces platform ownership
Cloud Run removes node pools, cluster upgrades, control-plane policy, capacity placement, and much of the runtime infrastructure from the team’s operating surface.
The team still owns the container, application lifecycle, service identity, resource limits, scaling policy, networking, data dependencies, observability, and failure behavior. Those are enough places to make consequential mistakes. Adding Kubernetes should buy a control the system uses, not merely more places to express taste.
For a small technical team, avoided coordination compounds. A new service can use the same deployment, IAM, logging, domain, secret, and VPC patterns without asking someone to become the resident cluster archaeologist.
Managed doesn’t remove architecture
Cloud Run will scale a poor dependency contract efficiently into failure.
Postgres-backed services still need connection budgets. Request timeouts still don’t terminate work. Private services still need ingress, routing, and IAM to agree. Direct VPC egress still needs subnet capacity and reconnect-safe clients. Jobs still need idempotency and restart semantics. Worker pools still need a scaling or capacity policy.
The platform removes infrastructure ownership, not workload thinking.
That’s why it’s a good default: engineering attention can stay on the boundaries that affect correctness instead of machinery every service would otherwise inherit.
Scale to zero is optional, not the thesis
Low-traffic services can scale to zero. Latency-sensitive services can keep minimum instances. Worker pools and managed instances can remain running. Jobs exist only for their executions.
Cloud Run remains useful when a workload needs warm or continuous compute. The question is whether its lifecycle fits one of the managed resource types, not whether the bill can reach zero while idle.
Keep networking proportional
Use Direct VPC egress for private dependencies by default. Design “internal-only” as a real access model across ingress, caller path, DNS, load balancing, and IAM.
Cloud Run can participate in substantial private systems. When the networking design becomes complex, ask whether that complexity comes from real topology or from trying to make independent services behave like a cluster without admitting it.
The default expires at the control plane
Move a workload when it requires Kubernetes APIs or controllers as part of its supported operating model.
Operators, custom resources, StatefulSets, admission policy, cluster scheduling, service-mesh assumptions, Kubernetes-native storage, or vendor support tied to Helm may make GKE the smaller honest system. Translating those dependencies into bespoke Cloud Run automation would rebuild a worse private platform.
That boundary is described in GKE Autopilot as the escape hatch from Cloud Run. Autopilot is usually the next step because it supplies Kubernetes while retaining managed nodes. Standard follows only when node-level control itself is required.
A single Kubernetes-shaped component doesn’t require moving everything. Keep independent services and jobs on Cloud Run while the component that needs Kubernetes runs on GKE.
When Cloud Run fits
Start with Cloud Run when the workload fits a service, job, worker pool, or managed instance and the required platform controls exist. Add minimum capacity, private networking, sidecars, GPUs, or storage when those are the actual requirements. None independently justifies a cluster.
Leave Cloud Run when avoiding Kubernetes costs more engineering than using it. Until then, cluster ownership adds complexity without solving a current requirement.
More in this domain: Infrastructure
Browse allHow we decide between Cloud SQL connectors, Auth Proxy, and private IP
Cloud SQL connectors, the Auth Proxy, and private IP are not interchangeable secure connection options. They change identity, routing, deployment shape, and how much network plumbing the team actually owns.
Safe scaling defaults for Cloud Run + Postgres
Cloud Run autoscaling is not a database strategy. Safe defaults keep the application from scaling itself into a Postgres incident before the team understands the workload.
IAM DB auth for Cloud SQL: when it simplifies security and when it complicates delivery
IAM DB auth can reduce password sprawl and make revocation cleaner, but it also turns database access into an identity operating model that depends on disciplined service-account boundaries.
Cloud Run request timeouts don't kill your code (so your architecture has to)
A Cloud Run request timeout ends the request, not necessarily the work. If the operation can outlive its caller, the system needs explicit job semantics instead of hope.
Cloud Run scaling from zero is a feature until it isn't
Scale to zero is a good default for request-driven services, until startup delay, warm-capacity needs, or instance caps turn it into user-visible reliability behavior instead of a pricing feature.
Related patterns
Direct VPC egress vs Serverless VPC Access for Cloud Run: our default
We default to Direct VPC egress for Cloud Run because it is the cleaner networking shape: fewer moving parts, no connector resource, and costs that scale with the service instead of beside it.
GKE Autopilot as the escape hatch from Cloud Run
When Cloud Run stops fitting, the next move is usually GKE Autopilot: more Kubernetes-shaped control without immediately taking on the full burden of Standard clusters.
"Internal-only" Cloud Run isn't just a checkbox
Making a Cloud Run service private is not one toggle. It is a decision about ingress, routing, caller path, and IAM working together as one access model.
When repeated Pulumi code earns abstraction and when it doesn't
We don't abstract repeated Pulumi code just because it shows up more than once. We do it when the shared shape is real, the behavior is stable enough to deserve a boundary, and the result is easier to read than the duplication it replaces.