Course outline

Google Cloud / Intermediate: Service Contracts and Operations / Lesson 10

Cloud Run Execution and Scaling

Design a request service around its container, identity, concurrency, timeout, and state contracts instead of assuming the platform fixes application behavior.

About 5 min readContent reviewed
On this page

Lesson goals

  • Explain the ingress container contract and service/job distinction.
  • Separate ingress policy from caller authorization.
  • Budget concurrency and backing-service demand.

A request service has a specific runtime contract

Cloud Run supports several execution patterns; this lesson focuses on request-serving services and contrasts jobs. A service’s ingress container must listen on the configured PORT on0.0.0.0, not only loopback, under the documented contract. A job should complete and exit rather than start an HTTP server. Features and execution environments have their own support requirements.

Container startup, request timeout, graceful termination, memory, CPU allocation, and concurrency settings affect application design. TLS termination and request forwarding follow the platform contract; do not assume a container port published locally proves the deployed application meets it. The course starts no container or server and makes no deployment claim.

Inspect synthetic runtime intent locally

The first Python program reviews a static model containing a listen address, port source, and persistent-state decision. It flags loopback as inconsistent with this service design and identifies local-only persistence as unsuitable for required durable state. It does not parse a real Cloud Run service, validate a container image, or discover environment variables.

The writable container filesystem has documented instance-lifetime behavior and is not a durable database. Externalize required state to an appropriate service and design its permissions and retry semantics. An in-memory cache can be useful only if the application tolerates loss and multiple independent instances.

python Review an invented service runtime model
model = {"listen": "127.0.0.1", "port_source": "PORT", "durable_state": "local-only"}
issues = []
if model["listen"] != "0.0.0.0": issues.append("listen-address review")
if model["durable_state"] == "local-only": issues.append("durability review")
print("; ".join(issues))
Expected output
listen-address review; durability review

The local convention finds two design gaps; it does not observe a running container.

Reachability and invocation authority are independent

Ingress controls which traffic paths may reach a service; authentication and IAM determine who may invoke it under the selected access configuration. A private path is not an automatic application grant, and a valid identity does not bypass every ingress restriction. Outbound VPC connectivity is another design question, separate from inbound request admission.

Use a dedicated runtime identity and an explicit caller-token audience where authentication requires it. Do not copy a developer login or a long-lived key into an image as a deployment shortcut. If a service calls Cloud SQL or Storage, review both the service account’s permissions and the network/client connection path.

Concurrency and instance counts form a workload envelope

The second program multiplies an invented instance count by per-instance concurrency. It yields a planning envelope of forty simultaneous request slots, not a throughput guarantee. CPU-bound handlers, shared state, connection pools, startup, and external latency can make the useful operating limit lower. Each handler must be safe for the concurrency actually permitted.

Maximum-instance settings limit scaling under documented semantics, but current documentation allows brief exceedance in some circumstances. Service and revision scope, traffic splitting, and rollout behavior matter. Do not use the simple product as an absolute connection cap or exact cost ceiling. Add backing-service headroom and admission control.

python Calculate a synthetic concurrency envelope
planned_instances = 5
concurrency_per_instance = 8
request_slots = planned_instances * concurrency_per_instance
print(f"planning_slots={request_slots}")
print("cloud capacity verified", False)
Expected output
planning_slots=40
cloud capacity verified False

Five times eight yields forty planning slots; actual Cloud Run capacity is not tested.

A revision rollout needs application evidence

Revisions and traffic controls support rollout patterns, but a successful configuration update does not prove user transactions or database compatibility. Keep immutable artifact identity, migration order, readiness, rollback, and session/state assumptions explicit. Retries after timeouts can duplicate effects, and a request ending does not guarantee every application side effect rolled back.

Observe request latency, errors, startup, saturation, and dependency health with the intended SLO. Test graceful shutdown and cancellation in an approved environment before relying on them. All examples here are offline design checks; the lesson neither deploys a revision nor changes ingress, identity, traffic, or scaling.

Common errors and fixes

The service listens only on127.0.0.1.

Why it happens
A local development binding was carried into the service runtime.
How to fix it
Follow the documented ingress-container address and PORT contract.
Prevent it next time
Review startup configuration before an authorized deployment.

Local container files are treated as durable shared state.

Why it happens
Instance lifetime was confused with persistence.
How to fix it
Use an appropriate external state service and explicit consistency design.
Prevent it next time
Test loss and multiple-instance behavior.

A maximum-instance number is called an exact connection ceiling.

Why it happens
Scaling semantics and per-instance clients were oversimplified.
How to fix it
Model pool demand, revision overlap, and documented limits.
Prevent it next time
Keep safety headroom and admission policy.

Check your understanding

1. A service has concurrency20 but uses one unsynchronized mutable request buffer. What is wrong even if it works at low traffic?

Show worked solution

Several requests in one instance may access the same buffer concurrently. Low-traffic success does not prove correctness under the configured concurrency. Use per-request state, a justified synchronization/ownership design, or a deliberately chosen lower concurrency with capacity consequences reviewed. Scaling to more instances does not repair an unsafe handler inside each instance.

2. Why should ingress, invoker authorization, and database access be tested as separate design questions?

Show worked solution

They govern different stages: allowed request path, caller authority at the service, and the runtime workload’s authority/connectivity to the database. One successful stage does not establish the others. Record principals, audiences, network paths, and target database permissions, and use approved environment-specific evidence before a real rollout. No single “private service” label proves the whole chain.

Key takeaways

  • Follow the contract of the selected Cloud Run execution pattern.
  • Instance lifetime, identity, ingress, and concurrency are separate design choices.
  • Planning arithmetic is not deployed capacity or policy evidence.

Official references