Skip to content

Google Cloud Run

Cloud Run is Google Cloud’s serverless container platform. Mosayic uses it to host your FastAPI backend in production.

  • Scales to zero. When nobody’s using your app, Cloud Run runs zero instances and you pay nothing. When traffic arrives, it spins up containers in seconds.
  • No infrastructure to manage. No VMs, no Kubernetes clusters, no load balancers to configure. You hand it a Docker image; it runs it.
  • Generous free tier. 2 million requests/month, 360,000 GB-seconds of memory, 180,000 vCPU-seconds — all free, every month, forever. Real apps stay inside this for a long time.
  • Standard Docker. Your container is just a normal Docker image. If you ever leave Cloud Run, the same image runs on AWS Fargate, Fly.io, Render, your own server — anywhere.
  • Same vendor as your dev tools. You’re already in Google Cloud for Secret Manager and (possibly) Firebase analytics. One vendor, one bill.

When you click Deploy API on the Production Release screen, the dashboard runs (via the extension):

Terminal window
cd <project>/api
gcloud run deploy api-prod \
--source . \
--region us-east1 \
--allow-unauthenticated \
--service-account compute-engine-sa@<project>.iam.gserviceaccount.com

--source . tells Cloud Run to:

  1. Build a container from your api/ folder using Cloud Build (no local Docker needed)
  2. Push the container to Artifact Registry
  3. Deploy a new revision to Cloud Run
  4. Route traffic to the new revision

You get back a URL like https://api-prod-abc123-uc.a.run.app. The dashboard then writes this into your mobile/eas.json so your production mobile builds know where to call.

Mosayic defaults to us-east1 because it’s cheap and reliable. You can change it on the Production Release screen.

If your users are concentrated in one region, deploying close to them reduces latency. The trade-off is that egress to other regions is slightly more expensive, but for most early-stage apps the difference is negligible.

Cloud Run scales to zero by default, which means after a period of no traffic, the first request to your API has to wait for a new container to spin up. This typically takes 200ms-2s for a Python FastAPI service.

If cold starts are a problem (e.g. your app feels sluggish after sitting idle):

  • Set min instances to 1 in the Cloud Run console — keeps one container warm at all times. Costs about $5-10/month per always-on container.
  • Optimize your container’s startup. The biggest wins are usually slimming down Python imports and avoiding heavy initialisation in module scope.

Cloud Run integrates with Secret Manager. Mosayic configures secret bindings during deploy:

spec:
containers:
- env:
- name: SUPABASE_SECRET_KEY
valueFrom:
secretKeyRef:
name: SUPABASE_SECRET_KEY
version: latest

The container starts up and finds the value in os.environ["SUPABASE_SECRET_KEY"]. The actual secret never touches your code or your repo.

The Compute Engine service account (used by Cloud Run by default) needs roles/secretmanager.secretAccessor for each secret. Mosayic grants this automatically when you set a secret via the dashboard.

Set a billing alert in the Google Cloud console to be notified if costs exceed a threshold. For a new project, $5/month is a reasonable initial alert.

If you ever see unexpected costs:

  • Check the Cloud Run Metrics tab for traffic spikes
  • Check Cloud Build logs (failed builds also cost a tiny amount each time)
  • Check egress (data leaving Google Cloud is the most expensive Cloud Run line item)

Cloud Run scales horizontally by default. With no configuration, it’ll spin up to 100 concurrent containers (the platform default), each handling up to 80 requests in parallel.

For most early-stage apps, this is fine — you’ll never approach the cap. If you need more, raise it in the Cloud Run service config.

You don’t have to use the Mosayic dashboard for deploys. From the api/ folder:

Terminal window
gcloud run deploy api-prod --source . --region us-east1

Or set up your own GitHub Action to deploy on push to main. Mosayic’s Production Release screen is a convenience, not a lock-in.

You don’t need to think about Cloud Run during local development — your API runs as a normal uvicorn process on your laptop. Cloud Run only enters the picture when you deploy.

You can test your container locally if you want:

Terminal window
cd api
docker build -t my-api .
docker run -p 8080:8080 -e SUPABASE_URL=... my-api

But the standard uvicorn dev server is faster for inner-loop development.