Cloud Run turns a container image into a managed HTTPS service, but successful operation still depends on build quality, runtime configuration, IAM, networking, and observability. For engineers preparing around the current Google Cloud Associate Cloud Engineer role, Cloud Run is a useful example of how Google Cloud separates application packaging from infrastructure operations: the platform manages servers and instance scaling, while the operator remains responsible for the container contract, service configuration, identity, and application behavior.
Troubleshooting is fastest when deployment and serving failures are separated. A revision that cannot start is different from a revision that starts but returns HTTP 500, and both are different from a request that is rejected by IAM or cannot reach a private dependency. Start from the platform’s observable state and classify the fault as build, startup, serving, access, or connectivity before changing settings. This keeps a networking change from obscuring an application exception, or an IAM change from masking a failed container startup.
Build an image that satisfies the Cloud Run container contract
Cloud Run expects a Linux container that can start reliably and listen on the port supplied through the PORT environment variable. The process should bind to all interfaces rather than only localhost, and the image architecture must be supported by the runtime. These requirements are simple but fundamental. Understanding the practical difference between virtual machines and containers helps because Cloud Run does not boot a general-purpose server for the application; it starts the containerized process under a managed runtime contract.
Validate the image locally before blaming the platform. Run it with an explicit PORT value, send a request to the listening address, and confirm the process stays alive. If the image was built on an ARM workstation, build for the supported target architecture or use Cloud Build. Keep startup logs concise enough that the first failure is visible instead of buried under framework noise.
Cloud Run starts a container under a managed execution contract; a service must listen on the supplied PORT value and bind to an address reachable by the platform, typically 0.0.0.0. A process that listens only on 127.0.0.1 can appear healthy inside its own container while the revision never becomes ready. Confirm image architecture, startup command and framework port configuration before changing networking or IAM. An HTTP service designed to run only as a local development server requires an explicit production listener configuration.
Deploy revisions deliberately
Each configuration change or image deployment creates a new revision. Revisions let operators inspect history, split traffic, and roll back without reconstructing an old environment from memory. Treat the revision name, image digest, environment variables, secrets, service account, CPU and memory, concurrency, timeout, and scaling settings as one release unit. That makes production behavior reproducible.
Use immutable image versions from Artifact Registry rather than ambiguous local tags. A disciplined image pipeline follows the same principles as building container images correctly: deterministic inputs, minimal unnecessary content, known dependencies, and a clear promotion path. Record the deployed digest in release notes so an incident responder can prove exactly which artifact served a request.
Revisions are immutable snapshots of a service’s deployable configuration, and traffic can be shifted between healthy revisions to limit the effect of a bad release. For a candidate build, record its image digest, environment variables, service identity, secrets, scaling and timeout values before increasing traffic. Split traffic is useful only when the monitoring distinguishes requests served by each revision. A rollback to a prior container cannot necessarily undo a database migration or an external side effect produced while the new revision was active.
Diagnose container startup failures first
When a revision never becomes ready, focus on startup rather than request routing. Common causes include not listening on PORT, binding only to 127.0.0.1, crashing during initialization, missing configuration, unsupported executable architecture, or taking too long before the process is ready. Cloud Run surfaces readiness and startup errors in deployment output and logs, which should be examined before changing unrelated IAM or networking settings.
Read stdout and stderr for the failed revision, reproduce the entrypoint locally with the same environment variables where possible, and remove optional startup work. Expensive migrations, large downloads, or dependency checks can make startup fragile. Move one-time operations to deployment workflows or jobs when they do not need to occur on every instance start.
A startup failure occurs before the service can accept traffic reliably, whereas a serving error happens after a revision can route requests. If a revision cannot become ready, inspect the container’s first logs for a failed startup command, wrong listener, missing variable, inaccessible secret or memory termination. A successful local container test does not reproduce every platform constraint. Fix one observed contract violation and redeploy rather than changing port, timeout, memory and IAM simultaneously and losing the diagnostic signal.
Separate serving errors from platform readiness
A ready revision can still return 4xx or 5xx responses because the application is misconfigured or a downstream service is failing. Use request logs, application logs, Error Reporting, and latency metrics to distinguish application exceptions from platform-level saturation. HTTP 500 usually indicates application failure; 503 can arise from unavailable instances, startup problems, or dependency pressure depending on context.
Correlate the failing request with revision name, trace or request identifier, and downstream calls. If only the newest revision fails, compare configuration and image digest with the previous revision. If all revisions fail simultaneously, check shared dependencies and Google Cloud service health before rolling back healthy application code.
HTTP status codes narrow the question but do not answer it alone. An application exception may produce a 500, whereas a 503 can reflect unavailable capacity, startup behavior or dependencies. A 403 at the front door can occur before application code runs because the caller lacks invocation authorization or a required identity token. Filter request logs by revision and trace ID, then compare application output with platform events before concluding that the container image itself is broken.
Verify authentication and invocation permissions
Cloud Run can require authenticated invocation or allow unauthenticated access, depending on the service design. A 403 often means the caller lacks the Cloud Run Invoker role, the request did not include a valid identity token, or an organization policy prevents public access. This is an authorization problem, not evidence that the container failed.
Identify the caller principal and the exact resource policy before granting broader roles. Prefer service-to-service authentication with dedicated identities, and keep public access an explicit design choice. When testing from the command line, make sure the token audience and service URL match the target revision or service endpoint.
A private Cloud Run service needs an authorized caller, not merely a caller on a private network. Check Google Cloud IAM authorization: confirm that the identity generating the request has the necessary Cloud Run invocation permission and uses an appropriate identity token, then check any organization restrictions or ingress configuration. An application service account used to call downstream APIs is a separate identity from the principal invoking the service. Fixing the runtime service account’s project role cannot repair a client that never supplied a valid invocation token.
Troubleshoot VPC and private dependency access
Cloud Run services often need databases, internal APIs, or private addresses in a VPC. Direct VPC egress or Serverless VPC Access can provide that path, but route selection, connector capacity, firewall policy, DNS, and the destination service can still fail. A working public endpoint does not prove that the application can reach its private dependencies.
Test the dependency from the running service context, not only from a developer laptop. Confirm whether all egress or only private ranges should use the VPC path. If DNS resolves a private name differently across networks, record the answer from the Cloud Run environment. Timeout patterns, connection refusals, and permission errors should be classified separately because each points to a different layer.
When a Cloud Run service calls an internal database, Direct VPC egress or a Serverless VPC Access connector can provide its outbound network path. Routes, firewall rules, DNS and the destination listener still control whether the connection succeeds. Private Google Access and private services access address distinct connectivity arrangements; neither substitutes for configuring the Cloud Run service’s own egress. Test a connection from the deployed revision with its service account rather than relying on a VM’s successful test of the same database hostname.
Tune scaling, concurrency, and resource limits
Cloud Run scales instances according to incoming work and service settings. Maximum instances can protect a database or budget, while minimum instances can reduce cold-start exposure. Concurrency determines how many requests an instance can handle at once, and CPU or memory limits shape how much work each instance can perform. These controls interact, so changing one can move the bottleneck rather than remove it.
Observe request latency, instance count, CPU, memory, and error rate before tuning. The broader discipline of actionable performance KPIs is useful here: choose metrics that represent user outcomes and resource pressure, not vanity counters. If higher concurrency raises tail latency, scale out sooner; if the downstream database saturates, cap instances and fix the dependency capacity instead.
Concurrency, CPU, instance limits and request timeout settings interact with downstream service capacity. Raising concurrency can improve efficiency for an I/O-heavy handler but overload a small database connection pool; imposing a tight maximum-instance limit protects a dependency yet can increase queueing or rejection under sudden load. Examine request distribution and p95 latency during a representative traffic burst before tuning all limits. Minimum instances can reduce cold starts, but they introduce ongoing cost that should be justified by a measurable latency requirement.
Use logs and traces to shorten diagnosis
Cloud Logging automatically captures platform and container output, and request logs provide status, latency, and revision context. Structured application logs make filtering more useful because severity, request IDs, customer-safe identifiers, and component names become searchable fields. Error Reporting and traces can then connect a visible symptom to the code path that produced it.
Do not log secrets or sensitive payloads merely to simplify troubleshooting. Good operational logging records what happened, where, and under which safe correlation identifier. Create saved queries for common incident patterns, such as startup failures, 5xx spikes, permission errors, and dependency timeouts, so responders do not reinvent searches during an outage.
Structured application logs should include safe request identifiers, service revision and error category so a failed request can be followed across dependent services. Use Cloud Logging request entries, container output and traces to isolate whether the failure began at routing, startup, application logic or an external API call. Correlate the exact deployment time with the first observed error rather than assuming the most recent release caused every incident. Avoid logging identity tokens or request bodies merely to improve the speed of diagnosis.
Build a rollback and verification routine
Cloud Run makes revision rollback straightforward, but rollback still needs a decision rule. Define what constitutes a failed release, how quickly traffic should be shifted, and how stateful dependencies are handled. A code rollback does not reverse a database migration or external configuration change automatically.
After rollback, verify user-visible recovery and compare logs with the failure period. Keep deployment changes small enough that the cause is understandable. The principles behind controlled cloud updates apply directly: stage changes, preserve a known-good version, measure the result, and make rollback safe before production traffic depends on the new revision.
A rollback decision should identify the exact symptom that warrants shifting traffic and the signal that proves restoration. Compare failure rates and latency for the new and last-known-good revisions, then validate a representative user operation after any traffic move. Reverting a revision does not reverse schema changes or requests already processed, so coordinate with stateful dependencies before a high-impact rollback. Preserve the failing revision’s logs and configuration for analysis rather than deleting evidence immediately after service health returns.