Google Cloud Run skill for Claude Code

Containers tuned for concurrency, cost and calm rollouts. Claude prepares containers that honor the Cloud Run contract, then picks concurrency, CPU allocation and instance limits from how the app actually behaves instead of defaults. Services run as dedicated service accounts with Secret Manager secrets, new revisions deploy with no traffic behind a tag, and traffic shifts in steps with an exact rollback command ready.

  • namecloud-run
  • size161 lines · ≈2,100 tokens
  • files1
  • licenseMIT
  • updated

What Claude sees before loading it

This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.

description: Deploys and tunes Google Cloud Run services and jobs - container contract ($PORT, SIGTERM, stateless), concurrency and CPU allocation, min and max instances, startup CPU boost and cold starts, Secret Manager secrets, service accounts and IAM invoker access, ingress and VPC egress, revisions with tagged canary traffic splits, jobs for batch work, and logs. Use when containerizing an app for Cloud Run, choosing concurrency or instance settings, fixing cold starts, timeouts or 503s, wiring secrets, or rolling out a new revision safely.

Try asking

  • Deploy this Node app to Cloud Run with secrets and a canary rollout
  • Our Cloud Run service has slow first requests and random 503s
  • Background work stops after the response on Cloud Run. Why?

Use it when

  • Containerizing and deploying a service or job to Cloud Run
  • Choosing concurrency, CPU allocation or instance limits
  • Cold starts, 503s, timeouts or memory errors on Cloud Run
  • Wiring Secret Manager, service accounts or VPC egress

Skip it when

How to check the result

The tagged canary URL passes health checks, canary metrics match the previous revision, and describe shows the dedicated service account, max instances and intended secrets.

The common mistake it prevents

Running background work after the response with request-based CPU, where Cloud Run throttles the instance and the work silently stalls.

~/.claude/skills/cloud-run/SKILL.md

--- name: cloud-run description: Deploys and tunes Google Cloud Run services and jobs - container contract ($PORT, SIGTERM, stateless), concurrency and CPU allocation, min… license: MIT ---

A healthy Cloud Run service starts in seconds, listens on $PORT, holds no local state, runs as a dedicated least-privilege service account, pulls secrets from Secret Manager, has concurrency and instance limits chosen from measured load, and ships new revisions with tagged previews and gradual traffic shifts.

Workflow

- [ ] 1. Read current config: gcloud run services describe SERVICE --region R --format export
- [ ] 2. Verify the container contract (port, startup time, SIGTERM, statelessness)
- [ ] 3. Choose concurrency, CPU/memory, CPU allocation mode, min/max instances
- [ ] 4. Identity: dedicated service account, invoker IAM, ingress
- [ ] 5. Secrets and config; VPC egress if private resources are needed
- [ ] 6. Deploy a tagged no-traffic revision; test; shift traffic gradually
- [ ] 7. Check logs, latency, instance count, and cost

2. Container contract

  • Listen on 0.0.0.0:$PORT (default 8080); never hardcode.
  • Start fast: the default startup probe is a TCP check on the port; heavy init (model loading, migrations) delays readiness and cold starts. Run migrations as a Cloud Run job, not at service startup.
  • On scale-in or deploy, the instance gets SIGTERM with 10 seconds before SIGKILL: stop accepting work, finish in-flight requests, flush logs.
  • Filesystem is in-memory and counts against memory; use Cloud Storage, a database, or mounted volumes (Cloud Storage FUSE, NFS) for durable data.
  • Log JSON to stdout; Cloud Logging parses severity, message, and logging.googleapis.com/trace fields for correlation.

3. Capacity settings

SettingGuidance
--concurrencyDefault 80, max 1000. Set to what one instance handles without latency rising: I/O-bound async apps 80-250; CPU-heavy or single-threaded runtimes 1-10
--cpu, --memoryStart 1 vCPU / 512Mi-1Gi; more than 1 vCPU only helps multi-threaded runtimes
CPU allocationRequest-based (default): CPU only during requests, background work is throttled. Instance-based (--no-cpu-throttling): CPU always on, needed for background threads, queues consumers, websockets housekeeping; billed for instance lifetime
--min-instances1+ for latency-sensitive services (idle min instances are billed at a lower rate)
--max-instancesAlways set: protects databases and budgets from runaway scaling
--cpu-boostStartup CPU boost; cheap win for JVM/Node/Python cold starts
--timeoutRequest timeout up to 3600 s; streaming and websockets are bounded by it

Database connections: max instances x per-instance pool size must stay below the database limit. Use Cloud SQL connectors or a pooler, and size pools to concurrency.

4. Identity and access

gcloud iam service-accounts create orders-api --display-name "orders-api runtime"
gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:orders-api@$PROJECT.iam.gserviceaccount.com --role roles/cloudsql.client
  • Every service runs as its own service account (--service-account), never the default Compute Engine account (it often has Editor).
  • Private services: --no-allow-unauthenticated and grant roles/run.invoker to calling service accounts; callers send an ID token with the service URL as audience.
  • Public services: --allow-unauthenticated (subject to org policy) and authenticate users in the app or via IAP / a load balancer.
  • --ingress internal or internal-and-cloud-load-balancing to block direct internet access when fronted by a load balancer with Cloud Armor.

5. Secrets, config, networking

gcloud secrets create db-password --replication-policy automatic
printf '%s' "$PASSWORD" | gcloud secrets versions add db-password --data-file=-
gcloud secrets add-iam-policy-binding db-password \
  --member serviceAccount:orders-api@$PROJECT.iam.gserviceaccount.com --role roles/secretmanager.secretAccessor
  • Expose as env var (--set-secrets DB_PASSWORD=db-password:latest) or mounted file (--set-secrets /secrets/db=db-password:latest). Env vars resolve at instance start; mounted latest files pick up new versions on read. Pin versions (:3) for reproducible rollbacks.
  • Plain config via --set-env-vars or --env-vars-file env.yaml; --update-env-vars changes some without replacing all.
  • Private resources (Memorystore, private Cloud SQL IP, internal services): Direct VPC egress (--network, --subnet, --vpc-egress private-ranges-only) is the default choice over Serverless VPC Access connectors.

6. Deploy and roll out

# Build from source with Cloud Build + buildpacks/Dockerfile, deploy without traffic
gcloud run deploy orders-api --source . --region europe-west1 \
  --service-account orders-api@$PROJECT.iam.gserviceaccount.com \
  --no-allow-unauthenticated --concurrency 80 --cpu 1 --memory 1Gi \
  --min-instances 1 --max-instances 20 --cpu-boost \
  --set-secrets DB_PASSWORD=db-password:latest \
  --no-traffic --tag canary

# Test the tagged URL: https://canary---orders-api-<hash>-ew.a.run.app
gcloud run services update-traffic orders-api --region europe-west1 --to-tags canary=10
gcloud run services update-traffic orders-api --region europe-west1 --to-latest       # promote
gcloud run services update-traffic orders-api --region europe-west1 --to-revisions orders-api-00041-abc=100   # rollback

For declarative config, keep service.yaml in the repo and apply with gcloud run services replace service.yaml --region R. In CI, deploy prebuilt images (--image REGION-docker.pkg.dev/PROJECT/REPO/orders-api:$SHA) built once and promoted across environments; authenticate CI via Workload Identity Federation, not key files. Production traffic changes need user confirmation.

Jobs

Batch and one-off work (migrations, exports, nightly processing) use Cloud Run jobs:

gcloud run jobs create migrate --image $IMAGE --region europe-west1 \
  --command "npm" --args "run,migrate" --service-account orders-api@$PROJECT.iam.gserviceaccount.com \
  --tasks 1 --max-retries 1 --task-timeout 15m
gcloud run jobs execute migrate --region europe-west1 --wait

Parallel jobs read CLOUD_RUN_TASK_INDEX and CLOUD_RUN_TASK_COUNT to shard work. Schedule with Cloud Scheduler. Make tasks idempotent; retries rerun the whole task.

Diagnosing common problems

SymptomLikely causeFix
Container failed to start and listen on portWrong port, binding to 127.0.0.1, slow startupBind 0.0.0.0:$PORT; reduce init; raise startup probe timeout
503 / “no available instance” burstsMax instances reached or slow scale-out with low concurrencyRaise max instances or concurrency; add min instances
High p99 on first requestsCold startsMin instances, CPU boost, lazy init, smaller image
Background tasks never finishRequest-based CPU throttles after responseInstance-based CPU, or move work to Cloud Tasks / Pub/Sub push
504 after N secondsRequest timeoutRaise --timeout or make the work async
Memory limit exceededWriting to the in-memory filesystem, leaksStream to GCS, raise memory, fix leak
gcloud run services logs read orders-api --region europe-west1 --limit 100
gcloud logging read 'resource.type="cloud_run_revision" AND resource.labels.service_name="orders-api" AND severity>=ERROR' --limit 50 --freshness 1h
gcloud run revisions list --service orders-api --region europe-west1

Gotchas

  • Default service account with Editor role is a common privilege problem; replace it.
  • --set-env-vars replaces all env vars; use --update-env-vars for one change.
  • Ingress internal blocks calls from Cloud Scheduler or other projects unless routed via VPC/LB.
  • Each deploy creates a revision; old revisions do not cost when not serving, but tags pin them for routing.
  • Request-based billing still charges for min instances while idle.

Verification

  1. curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $TAG_URL/healthz returns 200 on the canary tag before shifting traffic.
  2. Metrics during canary: error rate, p95 latency, container instance count, and CPU/memory utilization match or beat the previous revision.
  3. gcloud run services describe shows the dedicated service account, max instances, pinned or intended secret versions, and expected ingress.
  4. A deliberate redeploy during load shows no failed requests (SIGTERM handled).

About this skill

Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.

esc