How Cloud Run and Google Kubernetes Engine differ on scaling, billing, networking, operations and portability, for a backend with a few services and a database.
On Google Cloud, a containerized backend usually runs on Cloud Run or on Google Kubernetes Engine. Cloud Run is the shorter path: push a container, get an HTTPS endpoint that scales with traffic. GKE gives you the Kubernetes API and everything that comes with it, which matters once you need sidecars, custom networking or workloads that do not fit the request model.
A common question is when a backend outgrows Cloud Run. This guide compares the two on scaling, billing, networking and operations, and shows how Encore deploys the same services to either one with the same code on both.
Each option is covered below, starting with Encore.
Encore combines an open source infrastructure SDK for TypeScript and Go with a platform that provisions and deploys into your own AWS or GCP account. In a GCP environment you choose the compute platform: Cloud Run, or GKE in Autopilot or Standard mode. Databases become Cloud SQL for PostgreSQL, Pub/Sub topics become Google Cloud Pub/Sub with dead-letter topics, secrets live in Secret Manager, and each service gets its own service account.

The service code is the same on both platforms:
// inventory/inventory.go
package inventory
import (
"context"
"encore.dev/storage/sqldb"
)
// Cloud SQL for PostgreSQL on GCP, a local Postgres under encore run.
var db = sqldb.NewDatabase("inventory", sqldb.DatabaseConfig{
Migrations: "./migrations",
})
type Stock struct {
SKU string `json:"sku"`
Quantity int `json:"quantity"`
}
//encore:api public method=GET path=/stock/:sku
func Get(ctx context.Context, sku string) (*Stock, error) {
s := &Stock{SKU: sku}
err := db.QueryRow(ctx,
`SELECT quantity FROM stock WHERE sku = $1`, sku,
).Scan(&s.Quantity)
if err != nil {
return nil, err
}
return s, nil
}
The migration in inventory/migrations creates the stock table the queries use:
-- inventory/migrations/1_create_stock.up.sql
CREATE TABLE stock (
sku TEXT PRIMARY KEY,
quantity INTEGER NOT NULL
);
Run in your terminal to get started locally.
On Cloud Run, each service is deployed with health checks and zero-downtime rollouts behind a load balancer. On GKE, each service becomes a Kubernetes Deployment with its own service account, plus the Service and Ingress resources that connect it to Google Cloud Load Balancing with managed TLS certificates. You do not write the manifests in either case, and encore run starts Postgres locally so the migration and the endpoint can be tested before anything is deployed.
That makes the platform an environment decision. A team can run staging on Cloud Run to keep idle costs low and production on GKE Autopilot, and an agent changing the inventory service never needs to know which one it is targeting.
Cloud Run runs a container image as a service with an HTTPS URL. Instances are added as requests arrive, each one can handle many concurrent requests, and a service with no traffic can scale to zero. Billing is based on the CPU and memory your instances use, per Cloud Run pricing, so a quiet internal API costs very little.
At the edges, Cloud Run requests have a configurable timeout with a maximum of 60 minutes, background work outside a request needs CPU to stay allocated or a separate job, and reaching Cloud SQL or Memorystore on private IPs needs VPC egress configured on every service. Cloud SQL, Pub/Sub subscriptions, Secret Manager entries and the IAM bindings between them are all separate pieces you create and keep in sync.
GKE gives you a Kubernetes cluster whose control plane Google runs. In Autopilot mode Google also manages nodes and bills per Pod resource request; in Standard mode you manage node pools and pay for the underlying Compute Engine VMs. Both carry the cluster management fee of $0.10 per cluster per hour, with a free tier credit that covers one Autopilot or zonal cluster per billing account.
What you get is the whole Kubernetes ecosystem: Helm charts, operators, service meshes, long-running workers and fine-grained network policies. What you take on is the work around it: manifests or charts for every service, Workload Identity bindings, ingress configuration, version upgrades and the CI pipeline that applies all of it.
The choice is rarely permanent, but moving between the two by hand is a migration. Cloud Run service YAML is Knative-style and does not map one to one to Deployments and Ingress, and the IAM, networking and secret wiring has to be redone.
Pick Encore when you want your backend on Google Cloud in your own project with Cloud SQL, Pub/Sub, secrets and service accounts created from the code, and the freedom to run Cloud Run in one environment and GKE in another.
Pick Cloud Run for HTTP services with uneven traffic where scale to zero and minimal operations matter most. Pick GKE when you need Kubernetes itself: existing Helm charts, operators, a service mesh, or a platform team that already runs clusters.
Cloud Run runs containers as managed services that scale with requests, including down to zero, with no cluster to operate. GKE is managed Kubernetes: you get the full Kubernetes API for deployments, networking and custom controllers, and you manage the cluster configuration, either with Autopilot handling the nodes or with Standard node pools you size yourself.
For low or uneven traffic, usually yes, because Cloud Run can scale to zero and has no cluster fee. GKE charges a cluster management fee of $0.10 per cluster per hour (the free tier covers one Autopilot or zonal cluster per billing account) plus compute, which becomes competitive when many services run at steady utilization.
With Encore, the compute platform is chosen when you create a GCP environment, and the same TypeScript or Go code deploys to Cloud Run or GKE, so moving means creating a GKE environment and deploying to it, with Cloud SQL, Pub/Sub, Secret Manager and a service account per service created for you in either case.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.