PracticeVideosBlogFlashcards

13.1 Cloud Run Deployment and Scaling Configuration

Key Takeaways

  • Autoscaling considers CPU and concurrency, with capacity and quotas affecting results.

  • Minimum instances reduce but do not eliminate all cold starts.

  • Instance limits can temporarily be exceeded and revisions can overlap; reserve database capacity and enforce pooling.

Last updated: October 2026

Serverless Deployment Configuration on Cloud Run

Google Cloud Run is a managed serverless platform that deploys and runs containerized applications directly on Google's scalable infrastructure. Built upon the open Knative specification, Cloud Run abstracts away underlying cluster management, virtual machine provisioning, and OS patching, allowing developers to focus purely on application logic. Cloud Run handles HTTP requests, gRPC calls, WebSockets, and asynchronous events while scaling elastically from zero to thousands of container instances.

For the Google Cloud Professional Cloud Developer exam, mastering Cloud Run deployment requires a deep understanding of runtime scaling parameters, CPU throttling models, VPC networking architectures, secret mounting techniques, and declarative service schemas.


Cloud Run Deployment Workflows & Declarative Schemas

Cloud Run supports two deployment workflows: imperative CLI commands via gcloud run deploy and declarative manifest application via gcloud run services replace.

Imperative Deployment with gcloud run deploy

The gcloud run deploy command deploys container images from Artifact Registry to Cloud Run, automatically creating or updating the service and generating an immutable revision:

## Deploying a production-ready Cloud Run microservice
gcloud run deploy order-service \
    --image=us-central1-docker.pkg.dev/my-project/app-repo/order-service:v2.1.0 \
    --region=us-central1 \
    --platform=managed \
    --allow-unauthenticated \
    --port=8080 \
    --concurrency=80 \
    --cpu=2 \
    --memory=2Gi \
    --min-instances=2 \
    --max-instances=100 \
    --no-cpu-throttling \
    --ingress=all \
    --network=production-vpc \
    --subnet=backend-subnet \
    --vpc-egress=all-traffic \
    --set-env-vars=ENVIRONMENT=production,LOG_LEVEL=info \
    --set-secrets=/secrets/db-password=order-db-secret:latest \
    --service-account=sa-order-runner@my-project.iam.gserviceaccount.com

Declarative Service Schema (service.yaml)

In GitOps and CI/CD pipelines, Cloud Run services are declared using Knative-compliant YAML manifests adhering to the serving.knative.dev/v1 API group:

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: order-service
  namespace: 'my-project'
  annotations:
    run.googleapis.com/ingress: all
    run.googleapis.com/launch-stage: GA
spec:
  template:
    metadata:
      name: order-service-v2-1-0
      annotations:
        # Minimum and maximum autoscaling instances
        autoscaling.knative.dev/minScale: '2'
        autoscaling.knative.dev/maxScale: '100'
        # CPU allocation: false means CPU is always allocated
        run.googleapis.com/cpu-throttling: 'false'
        # Direct VPC egress network interface
        run.googleapis.com/network-interfaces: '[{"network":"production-vpc","subnetwork":"backend-subnet"}]'
        run.googleapis.com/vpc-access-egress: all-traffic
    spec:
      containerConcurrency: 80
      timeoutSeconds: 300
      serviceAccountName: sa-order-runner@my-project.iam.gserviceaccount.com
      containers:
        - image: us-central1-docker.pkg.dev/my-project/app-repo/order-service:v2.1.0
          ports:
            - name: http1
              containerPort: 8080
          resources:
            limits:
              cpu: '2000m'
              memory: '2Gi'
          env:
            - name: ENVIRONMENT
              value: 'production'
          volumeMounts:
            - name: db-secret-volume
              mountPath: /secrets
      volumes:
        - name: db-secret-volume
          secret:
            secretName: order-db-secret
            items:
              - key: latest
                path: db-password

To apply this declarative configuration, execute:

gcloud run services replace service.yaml --region=us-central1

Scaling Parameters: Concurrency, Min Instances & Max Instances

Cloud Run autoscaling operates at the instance level. Unlike Kubernetes Horizontal Pod Autoscaler (which scales based on average CPU or memory utilization), Cloud Run uses CPU and request-concurrency signals. CPU utilization is averaged across allocated vCPUs, which can hide a single busy thread on a multi-vCPU instance.

Request Concurrency (--concurrency)

Concurrency defines the maximum number of requests that can be processed simultaneously by a single container instance:

  • Default Value: 80 for console-created services; 80 times vCPU count for newly created CLI/Terraform services. Set the value explicitly for reproducible examples.
  • Configurable Range: 1 to 1000 requests per instance.

When the volume of incoming concurrent requests exceeds (current_instances * concurrency), Cloud Run can provision new container instances, subject to scaling behavior, quotas, and capacity to absorb the load.

Concurrency SettingOptimal Workload ProfileArchitectural Rationale
Concurrency = 1CPU-bound computation, image/video rendering, non-thread-safe runtimes (legacy Python/Ruby, C extensions)Ensures each container instance executes exactly one request at a time. Prevents CPU starvation and eliminates race conditions in non-thread-safe application code.
Concurrency = 80 (explicit example)Standard I/O-bound web services, REST APIs, Node.js / Go / Java async microservicesMaximizes resource efficiency by multiplexing multiple incoming HTTP requests over asynchronous network threads within a single container.
Concurrency > 250 (up to 1000)Ultra-lightweight asynchronous microservices, reverse proxies, static API redirectsMinimizes container instance sprawl and reduces overall compute cost for high-throughput, low-latency microservices. Requires adequate CPU and memory limits.

Exam Trap: CPU-heavy synchronous handlers can contend at high concurrency; I/O-bound single-threaded handlers can still overlap requests. Load-test latency and throughput, then consider reducing --concurrency (e.g., to 1 or 5) for compute-intensive tasks.

Cold Starts and Minimum Instances (--min-instances)

By default, Cloud Run scales down to zero instances when no traffic is present (--min-instances=0). When an incoming request arrives at an idle service, Cloud Run must provision container infrastructure, pull or load the image, execute the runtime binary, and wait for the application listening port to open. This introduces cold start latency (dependent on runtime, initialization and platform conditions).

To reduce baseline cold starts for latency-sensitive user-facing applications, configure minimum instances:

gcloud run services update order-service --min-instances=2 --region=us-central1

Operational and Cost Characteristics of Min Instances:

  1. Cloud Run keeps the specified number of container instances pre-warmed and ready to serve traffic immediately.
  2. When no requests are active, idle min instances with default CPU throttling are billed at a discounted idle rate (covering allocated memory and base infrastructure), drastically lowering costs compared to fully active compute.
  3. The warm baseline can absorb some requests; demand above that baseline and replacement instances can still incur cold starts.

Protecting Downstream Dependencies with Maximum Instances (--max-instances)

Cloud Run can scale up rapidly to hundreds or thousands of container instances. While this ensures frontend resilience during traffic surges, unbounded horizontal scaling can instantly overwhelm downstream stateful systems (such as Cloud SQL database connection pools, legacy mainframe APIs, or third-party rate-limited services).

Configuring --max-instances enforces an upper ceiling on horizontal expansion:

gcloud run services update order-service --max-instances=50 --region=us-central1

Calculating Safe Max Instances for Cloud SQL: If your Cloud SQL PostgreSQL instance supports a maximum of 500 connections, and your Cloud Run application maintains an internal connection pool of 10 connections per container instance, the nominal estimate is 50 * 10 = 500, leaving no margin. That is unsafe: overlapping revisions, temporary excess instances, administration, and other clients need headroom. Select a lower limit and enforce a shared database-side pool limit; the instance maximum is not a strict connection invariant.

Official references checked October 18, 2026: Google Cloud 1, Google Cloud 2.

Test Your Knowledge

A latency-critical authentication service deployed on Cloud Run experiences unacceptable 4-second latency spikes whenever new container instances scale up from zero under sudden morning login bursts. Furthermore, the service connects to an internal relational database that fails when total database connections exceed 120. Which combination of Cloud Run configuration parameters mitigates cold starts while safeguarding the backend database?

A

Set '--concurrency=1' and '--cpu-throttling' with '--max-instances=1000'

B

Set '--timeout=10s' and '--add-volume=type=in-memory' with '--min-instances=0'

C

Set '--ingress=internal' and '--vpc-egress=private-ranges-only' with '--min-instances=50'

D

Set '--min-instances=3' to keep warm instances ready, and set '--max-instances=12' as a nominal calculation for 10 connections per instance, with additional database headroom/pooling required

Sections you finish are checked off in the contents.