Cloud Run runs containers on Google Cloud without a cluster to manage. How services, jobs, concurrency and scaling to zero work, where it gets harder, and how to deploy a backend to it.
Google Cloud Run is the Google Cloud service for running containers without managing servers or a Kubernetes cluster: you hand it an image, it gives you an HTTPS URL, and it adds and removes instances as traffic changes, down to zero when nothing is calling. For a single stateless API it is one of the quickest ways onto Google Cloud.
It gets harder as the backend grows around it, since a database means Cloud SQL plus a connector or VPC setup, background work means Pub/Sub push subscriptions with their own service accounts, and each service needs its own deploy, secrets and IAM bindings, so the gcloud run deploy command that started it turns into a pile of scripts. This guide explains how Cloud Run works and what goes into running a full backend on it.
Each option is covered below, starting with Encore.
Encore is infrastructure from code for TypeScript and Go, with a platform that provisions and deploys into your own AWS or GCP account. On GCP you pick Cloud Run or GKE as the compute for an environment, and Encore builds the container, deploys each service to Cloud Run with health checks and zero-downtime rollouts, and provisions the Cloud SQL databases, Pub/Sub topics and buckets that the code declares.

A service with an API, a database and a topic is ordinary TypeScript:
// orders/orders.ts
import { api } from "encore.dev/api";
import { SQLDatabase } from "encore.dev/storage/sqldb";
import { Topic } from "encore.dev/pubsub";
const db = new SQLDatabase("orders", { migrations: "./migrations" });
export interface OrderPlaced {
orderId: number;
}
export const orderPlaced = new Topic<OrderPlaced>("order-placed", {
deliveryGuarantee: "at-least-once",
});
export const place = api(
{ expose: true, method: "POST", path: "/orders" },
async ({ sku }: { sku: string }): Promise<{ id: number }> => {
const row = await db.queryRow<{ id: number }>`
INSERT INTO orders (sku) VALUES (${sku}) RETURNING id`;
await orderPlaced.publish({ orderId: row!.id });
return { id: row!.id };
},
);
The migration in orders/migrations creates the orders table the queries use:
-- orders/migrations/1_create_orders.up.sql
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
sku TEXT NOT NULL
);
Run in your terminal to get started locally.
On GCP, the orders database becomes a Cloud SQL PostgreSQL database and order-placed a Pub/Sub topic, with the connection details and permissions wired up for the Cloud Run service, and Encore provisions an IAM role for the service with access to the resources it uses. Locally, encore run starts Postgres locally and runs the topic and its subscribers on your machine, so the same code runs on a laptop before anything reaches Google Cloud. That loop suits AI coding agents well: an agent that adds a subscriber or a table changes the code, runs it locally, and the next deploy creates the matching Cloud Run and Pub/Sub resources with no separate gcloud step. Sizing, minimum instances and regions stay adjustable per environment in the Encore dashboard or your own GCP console.
A Cloud Run service is a container image plus configuration: CPU and memory, environment variables, secrets mounted from Secret Manager, a service account, and scaling bounds. Every deploy creates an immutable revision, and traffic can be split between revisions for gradual rollouts or instant rollback. The container must listen on the port given in the PORT environment variable, 8080 by default, as described in the container runtime contract.
Each instance can serve several requests at once, 80 by default, which suits Node.js and Go servers that spend most of their time waiting on I/O. When requests stop, instances shut down, and the next request after an idle period pays a cold start while a new instance boots; setting minimum instances keeps some warm at the cost of paying for them while idle.
Cloud Run jobs run a container until it exits instead of serving requests, with optional parallel tasks that each get an index. They fit database migrations, nightly exports and batch processing, and Cloud Scheduler can start them on a cron schedule.
Connecting to Cloud SQL needs either the Cloud SQL connection built into Cloud Run or a private IP through Direct VPC egress, and Memorystore always needs VPC access. Pub/Sub delivers to Cloud Run through push subscriptions, which need an authenticated endpoint, a service account with the invoker role and retry settings per subscription. Each of those pieces lives outside the application code, in console clicks, gcloud commands or Terraform, which is the configuration that drifts between staging and production as services multiply. The pricing page also separates request-based from instance-based billing, so CPU-heavy background work inside a service can cost more than expected.
Cloud Run instances are stateless and their local disk is in memory, so anything written to the filesystem counts against the memory limit and disappears with the instance. Background work after the response is sent only gets CPU with instance-based billing or CPU always allocated. Outbound traffic comes from shared Google IPs by default; a static egress IP needs Cloud NAT and VPC routing, which Encore documents for its Cloud Run deployments in static outbound IP.
Cloud Run is a strong choice for stateless HTTP APIs and workers with uneven traffic, for teams already on Google Cloud, and for anything that should cost close to nothing when idle. GKE becomes the better fit when you need long-lived connections at large scale, GPUs with fine-grained scheduling, or workloads that are not request driven.
Pick Encore when you want a TypeScript or Go backend on Cloud Run in your own GCP project, with its databases, Pub/Sub topics and permissions created from the code you test locally with encore run.
Google Cloud Run is a managed compute platform that runs stateless containers on Google Cloud. You give it a container image, it gives you an HTTPS endpoint, and it scales the number of instances with traffic, down to zero when there are no requests.
A Cloud Run service runs a container that listens for HTTP requests and scales with traffic. A Cloud Run job runs a container to completion, for example a batch task or migration, and can be started manually, on a schedule or from a workflow.
Connect your GCP project in Encore, create an environment and choose Cloud Run as its compute. When you push, Encore builds a container for the app and deploys it to Cloud Run in your project, along with the Cloud SQL databases and Pub/Sub topics declared in the code.
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.