<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Caleb Duff</title>
    <description>The latest articles on DEV Community by Caleb Duff (@duffigoogle).</description>
    <link>https://dev.to/duffigoogle</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3750796%2F0b0e1f44-93cf-40c6-a9d9-d1f2f9fc3e23.jpg</url>
      <title>DEV Community: Caleb Duff</title>
      <link>https://dev.to/duffigoogle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/duffigoogle"/>
    <language>en</language>
    <item>
      <title>Managed Inference on Google Cloud: Pairing the Gemini Enterprise Agent Platform with Cloud Run</title>
      <dc:creator>Caleb Duff</dc:creator>
      <pubDate>Wed, 12 Aug 2026 15:45:27 +0000</pubDate>
      <link>https://dev.to/gdg/managed-inference-on-google-cloud-pairing-the-gemini-enterprise-agent-platform-with-cloud-run-246j</link>
      <guid>https://dev.to/gdg/managed-inference-on-google-cloud-pairing-the-gemini-enterprise-agent-platform-with-cloud-run-246j</guid>
      <description>&lt;p&gt;If you have ever wanted to ship an AI-powered application without managing GPUs, model servers, or scaling infrastructure yourself, this guide is for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Managed inference&lt;/strong&gt; simply means letting a cloud provider run the AI model for you: you send a request, the platform handles the compute, and you get a response back. On Google Cloud, the cleanest way to do this today is to pair the &lt;strong&gt;Gemini Enterprise Agent Platform&lt;/strong&gt; (formerly Vertex AI) with &lt;strong&gt;Google Cloud Run&lt;/strong&gt;, dividing responsibilities between the two services. The Agent Platform serves as the orchestration and intelligence engine, while Cloud Run hosts your custom application logic, front-end UIs, or &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By the end of this article, you will be able to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explain the hybrid architecture and why each layer exists&lt;/li&gt;
&lt;li&gt;Define an AI agent in code using the Agent Development Kit (ADK)&lt;/li&gt;
&lt;li&gt;Deploy your app layer to Cloud Run with a single command&lt;/li&gt;
&lt;li&gt;Choose between online and batch inference for your workload&lt;/li&gt;
&lt;li&gt;Secure and monitor the whole setup in production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;New to the underlying concept? Start with Google Cloud's primer: &lt;a href="https://cloud.google.com/discover/what-is-ai-inference?hl=en" rel="noopener noreferrer"&gt;What is AI inference?&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along hands-on, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Google Cloud project with billing enabled&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;gcloud&lt;/code&gt; CLI installed and authenticated&lt;/li&gt;
&lt;li&gt;Python 3.10+ and the ADK installed (&lt;code&gt;pip install google-adk&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also read this purely as an architecture walkthrough; every step is explained, not just shown.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Architectural Blueprint
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fakin92cmry0xpuej2hkr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fakin92cmry0xpuej2hkr.png" alt="GCP Inference lifecycle" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This pattern splits your system into independent, auto-scaling tiers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Client / Web UI ] ──&amp;gt; [ Cloud Run Service ] (App Logic / Tool Front End)
                                │
                                ▼
        [ Gemini Enterprise Agent Platform — Agent Runtime ]
            (Orchestration, Intent Analysis, Memory)
                                │
                                ▼
              [ Managed Inference / Model Garden ]
                 (Gemini 3.x Pro / Flash models)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why split it this way?&lt;/strong&gt; Each tier scales independently and fails independently. Your web front end can handle a traffic spike without touching the model layer, and you can swap models without redeploying your application code. It also creates a clean security boundary, clients only ever talk to Cloud Run, never directly to the model.&lt;/p&gt;

&lt;p&gt;Here is what each layer actually does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Run&lt;/strong&gt; runs your specialized business logic, secures client-facing endpoints with Identity-Aware Proxy (IAP), and hosts external tools, MCP servers, and APIs. Think of it as everything &lt;em&gt;you&lt;/em&gt; build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Agent Platform (Agent Runtime)&lt;/strong&gt; manages active agent state, long-term memory, and the model's reasoning steps in a centralized, fully managed runtime. Think of it as everything &lt;em&gt;Google&lt;/em&gt; runs for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Build Your Agent Code with the ADK
&lt;/h2&gt;

&lt;p&gt;Use the open-source &lt;strong&gt;Agent Development Kit (ADK)&lt;/strong&gt; to define your agent's behavior in code and bind it to a model. The key idea to understand: &lt;strong&gt;tools are plain Python functions&lt;/strong&gt;. The ADK reads each function's docstring to decide when and how to call it; so a clear docstring is not documentation nicety, it is part of your agent's logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# agent.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.adk.agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_internal_business_system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Invokes secure business workflows deployed on Cloud Run.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Logic to securely call your Cloud Run service URL
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Data retrieved from secure internal backend.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Define an agent that targets a current Gemini model
&lt;/span&gt;&lt;span class="n"&gt;root_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enterprise_inference_agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3.5-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Or another current model from Model Garden
&lt;/span&gt;    &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a data processing assistant using managed inference.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;call_internal_business_system&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Breaking down the four fields:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; — an identifier for your agent, used in logs and traces.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;model&lt;/code&gt; — which Gemini model handles the reasoning. Flash models are faster and cheaper; Pro models handle more complex reasoning.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;instruction&lt;/code&gt; — the agent's system prompt, shaping its behavior on every request.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tools&lt;/code&gt; — the Python functions the model is allowed to call. When a user request matches a tool's docstring, the model invokes it.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Gemini 1.0 and 1.5 models (including &lt;code&gt;gemini-1.5-pro&lt;/code&gt;) have been retired and now return errors. Always target a currently supported model, such as &lt;code&gt;gemini-3.5-flash&lt;/code&gt;, &lt;code&gt;gemini-3.6-flash&lt;/code&gt;, or a Gemini 3.x Pro release from Model Garden.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. Containerize and Deploy the App Layer to Cloud Run
&lt;/h2&gt;

&lt;p&gt;When deploying your orchestration backend or front-end dashboard, the tooling can package and push the container for you. Two small steps get you there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step A: Configure Service Account Permissions
&lt;/h3&gt;

&lt;p&gt;In Google Cloud, services do not trust each other by default, your Cloud Run instance needs explicit permission to invoke Agent Platform endpoints. This command grants its service account that permission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud projects add-iam-policy-binding YOUR_PROJECT_ID &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"serviceAccount:YOUR_RUN_SA@YOUR_PROJECT_ID.iam.gserviceaccount.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"roles/aiplatform.user"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In plain terms: "let this Cloud Run service call the AI platform." This is the step people most often forget; if your deployed service returns permission errors, come back here first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step B: Build and Deploy
&lt;/h3&gt;

&lt;p&gt;The ADK ships with a one-command deployment path. Under the hood, it does three things: builds your container image, pushes it to Artifact Registry, and creates (or updates) the Cloud Run service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Deploys your custom agent or tool layer directly to Cloud Run&lt;/span&gt;
adk deploy cloud_run &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_PROJECT_ID"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--service_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"agent-inference-backend"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    path/to/your/agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, the &lt;strong&gt;Agents CLI&lt;/strong&gt; (&lt;code&gt;agents-cli&lt;/code&gt;) can scaffold the deployment configuration for a Cloud Run target. For example, &lt;code&gt;agents-cli scaffold enhance --deployment-target cloud_run&lt;/code&gt; and works from inside your preferred AI coding tool. Either route wires up your environment variables, including model targets and the public service URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Online and Batch Inference Routines
&lt;/h2&gt;

&lt;p&gt;Once the plumbing is in place, there are two primary ways to trigger managed inference. Choosing correctly comes down to one question: &lt;strong&gt;does a human need the answer right now?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Online inference (low-latency UI):&lt;/strong&gt; Make synchronous API calls from your Cloud Run front end directly to the deployed agent endpoint for real-time chat, tool calls, or step-by-step reasoning. &lt;em&gt;Example: a customer support chatbot where every second of latency matters.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch inference (high-volume data):&lt;/strong&gt; For large data processing jobs, submit an asynchronous batch prediction job through the Agent Platform SDK. The platform provisions dedicated compute, runs the inference tasks, writes results and logs to Cloud Storage, and tears down the compute automatically when the job completes. &lt;em&gt;Example: classifying 100,000 support tickets overnight; nobody is waiting on a single response, so throughput and cost matter more than latency.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Batch jobs are typically much cheaper per request, so a good rule of thumb is: default to batch, and reserve online inference for genuinely interactive experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Secure and Monitor the Architecture
&lt;/h2&gt;

&lt;p&gt;A demo can skip this section. Production cannot.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secure the ingress:&lt;/strong&gt; Wrap your Cloud Run endpoints in Identity-Aware Proxy (IAP) to protect human-in-the-loop dashboards, IAP checks the user's Google identity &lt;em&gt;before&lt;/em&gt; traffic ever reaches your code. For agent-to-tool traffic, Agent Gateway can give each agent a unique identity with end-to-end mTLS (mutual TLS, where both sides verify each other) when calling MCP servers on Cloud Run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralize trace logging:&lt;/strong&gt; Enable the platform's built-in OpenTelemetry tracing (Cloud Trace is on by default for CLI-based deployments). You can visually inspect directed acyclic graphs (DAGs) of execution, a step-by-step map of every reasoning step, model call, and tool invocation — to see exactly how your Gemini models and Cloud Run tools collaborated on an inference task. When an agent gives a strange answer, this trace is how you find out &lt;em&gt;why&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Split the responsibilities:&lt;/strong&gt; Cloud Run for your code, the Agent Platform for orchestration and models. Each tier scales and fails independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools are just functions:&lt;/strong&gt; the ADK turns well-documented Python functions into capabilities your agent can call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permissions before deployment:&lt;/strong&gt; grant &lt;code&gt;roles/aiplatform.user&lt;/code&gt; to your Cloud Run service account, or nothing else will work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Match inference mode to workload:&lt;/strong&gt; online for interactive experiences, batch for high-volume processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure and trace from day one:&lt;/strong&gt; IAP at the edge, mTLS between services, OpenTelemetry for visibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where to Go Next
&lt;/h2&gt;

&lt;p&gt;Try the smallest possible version: define a one-tool agent with the ADK, run &lt;code&gt;adk deploy cloud_run&lt;/code&gt;, and send it a request. Once that works, everything else in this article is an incremental addition.&lt;/p&gt;

&lt;p&gt;Have you tried pairing the Agent Platform with Cloud Run, or are you still on a self-managed inference setup? I would love to hear what your architecture looks like in the comments.&lt;/p&gt;

</description>
      <category>cloudrun</category>
      <category>geminienterpriseagentplatform</category>
      <category>googlecloud</category>
      <category>ai</category>
    </item>
    <item>
      <title>Cloud Run Sandboxes: The Safest Way to Run AI-Generated Code in Production</title>
      <dc:creator>Caleb Duff</dc:creator>
      <pubDate>Mon, 27 Jul 2026 13:45:29 +0000</pubDate>
      <link>https://dev.to/duffigoogle/cloud-run-sandboxes-the-safest-way-to-run-ai-generated-code-in-production-4k1o</link>
      <guid>https://dev.to/duffigoogle/cloud-run-sandboxes-the-safest-way-to-run-ai-generated-code-in-production-4k1o</guid>
      <description>&lt;p&gt;Generative AI applications and autonomous agents (AI agents) are revolutionizing how software interacts with code, thereby creating a new challenge. Modern AI agents no longer just generate static text, these agents have evolved, dynamically generating codes,  write and execute Python scripts, parse datasets, run web scrapers, and invoke external webhooks in real time.  If an untrusted code executes inside your main application container, an attacker or a hallucinating LLM could access environment variables, steal service account tokens from the cloud metadata server, or compromise internal networks; this posses massive security risk. &lt;br&gt;
The question becomes, how do you let a language model execute code without putting your infrastructure at risk?&lt;/p&gt;

&lt;p&gt;Google recently answered the question above by addressing one of the hardest challenge in AI engineering, which is a fundamental change in how you can safely build AI agents that execute code and it is deeply integrated into the serverless model you already know. Google Cloud introduced Cloud Run Sandboxes in public preview. Woohoo!&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Google Cloud Run Service Sandbox?
&lt;/h2&gt;

&lt;p&gt;Cloud Run Sandboxes are lightweight, isolated execution boundaries that you spawn near-instantly &lt;code&gt;within your existing Cloud Run service instances&lt;/code&gt;. Cloud Run Sandboxes give you a secure, isolated sandbox to run these tasks without leaving your serverless environment.&lt;/p&gt;

&lt;p&gt;The key phrase is &lt;code&gt;within your existing Cloud Run service instances&lt;/code&gt;. You do not spin up a separate Cloud Run service to act as a sandbox host. You do not provision a new VM. The sandbox runs inside the same instance that is already executing your agent code, isolated from it by two layers of security boundaries, but co-located with it for speed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpwchbkxo0l02ntfhpcrq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpwchbkxo0l02ntfhpcrq.png" alt="Cloud Run Overview Interface on Google Cloud Console" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you enable the feature on a Cloud Run service, a sandbox command-line tool is mounted into your execution environment (container), allowing applications to safely start sandboxes through standard subprocess calls without risking the host system.&lt;br&gt;
Think of it as giving your agent a locked room inside your locked building. The agent can go into that room, execute whatever code it needs to, and come back out, but nothing that happens in the room can touch the building's keys, wiring, or front door.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key Capabilities:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Millisecond Startup: Spawns fresh execution environments in roughly ~500ms directly inside the active host container.&lt;/li&gt;
&lt;li&gt;Shared Resource Pricing: Runs on your instance’s already-allocated CPU and memory, meaning there are no additional cloud VM charges or specialized third-party vendor markups.&lt;/li&gt;
&lt;li&gt;Strict Ephemerality: Once execution completes, the sandbox process and its filesystem changes are discarded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fny9p4c2nzom7ahw5qs7e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fny9p4c2nzom7ahw5qs7e.jpg" alt="Cloud Run Service Instance with an isolated Agent sandbox " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Use It? (The Security &amp;amp; Operational Benefits)
&lt;/h2&gt;

&lt;p&gt;Historically, sandboxing dynamic code required complex infrastructure setups. Cloud Run Sandboxes are engineered to protect your host application and cloud resources from malicious or erroneous code execution, by establishing three strict &lt;code&gt;Zero-trust&lt;/code&gt; security boundaries out of the box:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Credential, identity protection and environment isolation:&lt;/strong&gt; By default, sandboxes do not have access to the parent workload, cannot read host environment variables, secrets, or the Google Cloud metadata server, thereby preventing unauthorized access to project service account tokens. All sandboxes are completely isolated from each other.&lt;br&gt;
This is the boundary that matters most for AI agent workloads. A prompt injection attack that convinces your agent to run malicious code gains nothing, the sandbox has no access to your service account, your Secret Manager values, or the metadata server that would give it a token to act on your behalf.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Network Egress Blocked by Default:&lt;/strong&gt; By default, sandboxes have &lt;strong&gt;zero outbound network access&lt;/strong&gt; from inside the sandbox. If your agent is tricked into running a script that attempts to exfiltrate data to a malicious server, the network request is blocked at the system layer.&lt;br&gt;
Egress is only possible when you explicitly enable it per execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Egress disabled (default) — any outbound network call is blocked&lt;/span&gt;
sandbox &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; python3 /tmp/generated_script.py

&lt;span class="c"&gt;# Egress enabled — for sandboxes that need to call external APIs&lt;/span&gt;
sandbox &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nt"&gt;--allow-egress&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; curl https://api.github.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a meaningful security default. Most code interpretation tasks, data analysis, calculation, text processing, chart generation; require no outbound connectivity. Locking it down by default means a compromised prompt cannot phone home, even if it tries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Safe filesystem overlay (Zero-Trust Process Isolation):&lt;/strong&gt; Code inside the sandbox operates with limited system permissions and is strictly isolated from neighboring sandboxes and the host process. The sandbox runs with a read-only view of your container's filesystem (allowing it to use your installed packages, Python runtimes, and binaries) but writes all changes to an isolated, temporary memory overlay. Once the sandbox execution ends, all generated files are discarded.&lt;/p&gt;

&lt;p&gt;This means your agent's dependencies, runtimes, and tools are available inside the sandbox, it can run python3, use numpy, call playwright; but any files written during execution disappear when the sandbox closes. If you need to persist output across sandboxes, you do so explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Write sandbox output to a tar archive that persists outside the sandbox&lt;/span&gt;
sandbox &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nt"&gt;--write&lt;/span&gt; &lt;span class="nt"&gt;--export-tar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/work.tar &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"mkdir -p /tmp/work &amp;amp;&amp;amp; echo 'task-complete' &amp;gt; /tmp/work/status.txt"&lt;/span&gt;

&lt;span class="c"&gt;# Import the archive into a new sandbox&lt;/span&gt;
sandbox &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nt"&gt;--write&lt;/span&gt; &lt;span class="nt"&gt;--import-tar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/work.tar &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt; /bin/bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"cat /tmp/work/status.txt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Use Cloud Run Sandboxes: Step by step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Enabling the feature (sandbox launcher) at deploy time
&lt;/h3&gt;

&lt;p&gt;To use Cloud Run Sandboxes, you need to deploy a Cloud Run service with the feature enabled. Enabling sandboxes on your Cloud Run service is as simple as adding a single flag to your deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud beta run deploy my-app-agentic-service &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gcr.io/my-project/agent-image &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;africa-south1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--sandbox-launcher&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min-instances&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--concurrency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or via a YAML configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;serving.knative.dev/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app-agentic-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;run.googleapis.com/sandbox-launcher&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcr.io/my-project/agent-image&lt;/span&gt;
        &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2"&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Gi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Spawn sandboxes from your agent code
&lt;/h3&gt;

&lt;p&gt;Once the sandbox launcher is enabled, the sandbox binary automatically becomes available inside your container. Your agents code calls it via standard subprocess execution. &lt;br&gt;
&lt;strong&gt;Key subcommands include:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sandbox do&lt;/td&gt;
&lt;td&gt;Creates a temporary sandbox, executes a command, and destroys it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sandbox run&lt;/td&gt;
&lt;td&gt;Starts a sandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sandbox exec&lt;/td&gt;
&lt;td&gt;Executes a command in a running sandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sandbox tar&lt;/td&gt;
&lt;td&gt;Takes a snapshot of the sandbox's filesystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sandbox delete&lt;/td&gt;
&lt;td&gt;Deletes a sandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h4&gt;
  
  
  Sample: Executing a Python code or Nodejs code or Go code
&lt;/h4&gt;

&lt;p&gt;Here's a practical example showing how an AI agent uses the sandbox to execute generated code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import subprocess

def run_llm_generated_code(llm_code: str) -&amp;gt; str:
    """
    Safely execute code generated by an LLM inside an isolated sandbox.
    The sandbox has no access to env vars, secrets, or network by default.
    """
    # Write the generated code to a temp file in the host container
    with open("/tmp/generated_script.py", "w") as f:
        f.write(llm_code)

    result = subprocess.run(
        ["sandbox", "do", "--", "python3", "/tmp/generated_script.py"],
        capture_output=True,
        text=True,
        timeout=30   # hard timeout, the sandbox is killed after this
    )

    if result.returncode == 0:
        return result.stdout
    else:
        return f"Execution failed:\n{result.stderr}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Node.js agent example
const { execSync } = require('child_process');
const fs = require('fs');

function runUntrustedCode(llmCode) {
  fs.writeFileSync('/tmp/generated_script.py', llmCode);

  try {
    const output = execSync(
      'sandbox do -- python3 /tmp/generated_script.py',
      { timeout: 30000, encoding: 'utf8' }
    );
    return { success: true, output };
  } catch (err) {
    return { success: false, error: err.stderr };
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Go agent example
package main

import (
    "bytes"
    "os"
    "os/exec"
)

func runInSandbox(code string) (string, error) {
    // Write code to temp file
    if err := os.WriteFile("/tmp/script.py", []byte(code), 0644); err != nil {
        return "", err
    }

    cmd := exec.Command("sandbox", "do", "--", "/usr/bin/python3", "/tmp/script.py")
    var out, errBuf bytes.Buffer
    cmd.Stdout = &amp;amp;out
    cmd.Stderr = &amp;amp;errBuf

    if err := cmd.Run(); err != nil {
        return "", fmt.Errorf("sandbox error: %s", errBuf.String())
    }
    return out.String(), nil
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;sandbox do&lt;/code&gt; command creates a temporary sandbox, runs the Python code, and returns the output. Because sandboxes don't inherit host environment variables, you must use absolute paths for commands&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Use the ADK integration (for Gemini-based agents)
&lt;/h3&gt;

&lt;p&gt;Cloud Run Sandboxes are supported in the Agent Development Kit (ADK) with a new &lt;code&gt;CloudRunSandboxCodeExecutor&lt;/code&gt;. This integration gives ADK agents running on Cloud Run the ability to execute code in a single line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from google.adk.agents import Agent
from google.adk.integrations.cloud_run import CloudRunSandboxCodeExecutor

analyst_agent = Agent(
    name="data_analyst",
    model="gemini-3.1-pro-preview",
    system_instruction=(
        "You are an expert data analyst. Write and execute Python code "
        "to answer user questions and process data safely."
    ),
    code_executor=CloudRunSandboxCodeExecutor(),
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the cleanest integration path if you are already building on ADK. The executor handles the &lt;code&gt;sandbox do&lt;/code&gt; invocation, output capture, error handling, and result formatting automatically, your agent just writes code and gets results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Use ComputeSDK for vendor-agnostic integration
&lt;/h3&gt;

&lt;p&gt;Cloud Run Sandboxes are also available via ComputeSDK, a vendor-agnostic SDK for running sandboxes. This SDK allows you to either invoke sandboxes remotely from outside the Cloud Run service or use them directly as a local tool on the service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Using ComputeSDK with Cloud Run Sandboxes
npm install @computesdk/cloud-run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLOUD_RUN_SANDBOX_URL=https://your-gateway-xyz.run.app
CLOUD_RUN_SANDBOX_SECRET=your_shared_secret
# Optional: Google-signed identity token for IAM-authenticated services
CLOUD_RUN_AUTH_TOKEN=your_identity_token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Use the Cloud Run provider
import { cloudRun } from '@computesdk/cloud-run';

const compute = cloudRun({
  sandboxUrl: process.env.CLOUD_RUN_SANDBOX_URL,
  sandboxSecret: process.env.CLOUD_RUN_SANDBOX_SECRET,
});

// Create sandbox
const sandbox = await compute.sandbox.create();

// Run a command
const result = await sandbox.runCommand('echo "Hello from Cloud Run!"');
console.log(result.stdout); // "Hello from Cloud Run!"

// Clean up
await sandbox.destroy();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ComputeSDK is the right choice when you want your agent code to be portable across sandbox providers — you can swap between Cloud Run Sandboxes, E2B, Modal, and others by changing the &lt;code&gt;provider&lt;/code&gt; parameter. &lt;a href="https://docs.computesdk.com/providers/cloud-run" rel="noopener noreferrer"&gt;Read more about ComputeSDK and CloudRun integration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwyz3dfglq9bh2k4aaimi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwyz3dfglq9bh2k4aaimi.png" alt="Cloud Run Sandboxes: Safe AI Code Execution" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Core use cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  - LLM code interpreters and data analysis
&lt;/h3&gt;

&lt;p&gt;This is the flagship use case. You can build advanced data analysis features into your AI products, let your models write and execute Python, R, or SQL code to analyse datasets, generate charts, and perform complex maths securely.&lt;/p&gt;

&lt;p&gt;A financial reporting agent that writes and executes pandas code to process a user's uploaded CSV. A scientific assistant that writes numpy code to run statistical analysis. A business intelligence tool where users ask natural language questions and the agent writes the SQL or Python to answer them. All of these involve LLM-generated code that could theoretically be malicious, and Cloud Run Sandboxes isolate every execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  - Headless browser automation
&lt;/h3&gt;

&lt;p&gt;You can give your agents a secure environment to run browsers, safely scraping web pages, taking screenshots, and automating web workflows without risking your host machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Launch a headless Playwright browser inside a sandbox
def web_research(url: str) -&amp;gt; str:
    script = f"""
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    page.goto('{url}')
    content = page.content()
    browser.close()
    print(content[:5000])  # Return first 5000 chars
"""
    with open("/tmp/browse.py", "w") as f:
        f.write(script)

    result = subprocess.run(
        ["sandbox", "do", "--allow-egress", "--", "python3", "/tmp/browse.py"],
        capture_output=True, text=True, timeout=30
    )
    return result.stdout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that browser automation requires &lt;code&gt;--allow-egress&lt;/code&gt; since it needs to reach the target URL. This is a deliberate choice, you are explicitly granting network access for this specific execution only.&lt;/p&gt;

&lt;h3&gt;
  
  
  - User-submitted code and plugins
&lt;/h3&gt;

&lt;p&gt;Beyond AI, platforms hosted on Cloud Run can use sandboxes to safely run custom scripts, plugins, or webhooks uploaded by their own end-users.&lt;/p&gt;

&lt;p&gt;SaaS platforms that allow user-defined automation scripts, webhook processors, custom plugin systems, or configurable data transformations, any of these involve running code you did not write, from users you may not fully trust. Cloud Run Sandboxes provide the isolation layer without requiring you to build and operate your own sandbox infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  - Sub-agent execution
&lt;/h3&gt;

&lt;p&gt;AI systems that spawn sub-agents to complete tasks in parallel, each sub-agent running a different piece of generated code, benefit directly from Cloud Run Sandboxes' per-sandbox isolation. Each sub-agent's code runs in a completely separate sandbox with no access to sibling sandboxes' state, data, or credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Cloud Run Sandboxes specifically?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Speed that matters for agent responsiveness
&lt;/h3&gt;

&lt;p&gt;Sandboxes are interactive and ready to execute commands almost instantly. By creating sandboxes within an existing Cloud Run resource where your agent runs, you reduce creation times when compared to creating a new Cloud Run resource for every task. This efficiency helps ensure that your agent remains responsive.&lt;/p&gt;

&lt;p&gt;In testing, 1,000 sandboxes were started, executed, and stopped with an average of 500ms latency. At this speed, sandbox creation is not a bottleneck in your agent's response time, it is a negligible overhead compared to the LLM inference calls your agent is already making.&lt;/p&gt;

&lt;h3&gt;
  
  
  - No additional cost
&lt;/h3&gt;

&lt;p&gt;Unlike dedicated sandbox hosting platforms that charge high premiums for on-demand virtual machines, Cloud Run Sandboxes run directly on your existing allocated CPU and memory. Because the sandboxes share the resources of your running instances, there is no additional cost or premium to use this feature.&lt;/p&gt;

&lt;p&gt;This is the economics argument that is easy to underestimate. Specialised sandbox services charge per execution, per second of CPU time, or per GB of memory, and those costs compound quickly for agent workloads that execute code frequently. Cloud Run Sandboxes add no line item to your bill.&lt;/p&gt;

&lt;h3&gt;
  
  
  - Native GCP integration
&lt;/h3&gt;

&lt;p&gt;Cloud Run Sandboxes work directly with the rest of your GCP stack. Your agent service already has its IAM service account, its Secret Manager access, its VPC configuration. The sandbox runs within that same resource, benefiting from all your existing security controls while being isolated from your agent's own context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to use Cloud Run Sandboxes
&lt;/h2&gt;

&lt;p&gt;Cloud Run Sandboxes are the right choice in the following scenarios:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI agents that execute code.&lt;/strong&gt; Any agent built with ADK, LangChain, LlamaIndex, or custom orchestration that uses code execution as a tool. The security boundaries are purpose-built for this use case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-tenant SaaS platforms.&lt;/strong&gt; If your platform runs code on behalf of multiple customers, sandboxes ensure one tenant's execution cannot interfere with, read from, or affect another tenant's data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data analysis and scientific computing tools.&lt;/strong&gt; Products that let users write or generate code to analyse their data, whether that code is human-authored or LLM-generated; benefit from sandbox isolation to protect the underlying platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook and plugin processors.&lt;/strong&gt; Systems that receive and execute code from external sources (third-party webhooks, user-uploaded plugins, custom integrations) need execution isolation that does not require a separate microservice per plugin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development and testing environments.&lt;/strong&gt; CI/CD pipelines that need to execute user-submitted code samples as part of automated testing can use sandboxes to isolate each test execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative options
&lt;/h2&gt;

&lt;p&gt;Cloud Run Sandboxes are not the only way to run untrusted code. Understanding the alternatives clarifies where sandboxes sit in the market.&lt;/p&gt;

&lt;h3&gt;
  
  
  E2B (e2b.dev)
&lt;/h3&gt;

&lt;p&gt;E2B provides an API-based sandbox service specifically designed for AI agents and code execution. It supports multiple runtimes, long-lived sandboxes, and a rich SDK with filesystem and terminal APIs. It is vendor-agnostic and integrates with any cloud. The trade-off: it is a third-party service with per-execution pricing, external API calls from your agent, and a dependency outside your GCP environment. For teams deeply invested in GCP, Cloud Run Sandboxes eliminate the external dependency entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modal
&lt;/h3&gt;

&lt;p&gt;Modal provides on-demand serverless functions for Python workloads with strong isolation and fast cold starts. It is excellent for Python-heavy workloads and data science tasks. Like E2B, it is vendor-specific and adds an external billing relationship. Modal's container-level isolation is strong but does not provide the same per-execution zero-trust credential isolation that Cloud Run Sandboxes enforce by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Firecracker microVMs (self-managed)
&lt;/h3&gt;

&lt;p&gt;Firecracker is the open-source microVM technology used by AWS Lambda and Fly.io. You can run your own Firecracker-based sandbox fleet on GCE. It provides genuine VM-level isolation and full control over the runtime environment. The cost is a significant operational overhead, because building, operating, scaling, and patching a Firecracker cluster is a meaningful engineering investment. Cloud Run Sandboxes give you comparable isolation without the operational surface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Run Jobs (async execution)
&lt;/h3&gt;

&lt;p&gt;For asynchronous execution, you can avoid disrupting the main application flow by executing tasks asynchronously using a Cloud Run Job for longer-running or background tasks. For example, execute a Cloud Run job that uploads code to Cloud Storage, installs the required dependencies, and then processes and stores the results back in Cloud Storage.&lt;/p&gt;

&lt;p&gt;This pattern predates Cloud Run Sandboxes and still has its place for long-running tasks (batch analysis, video processing, model fine-tuning) where you need full job-level isolation and are not latency-sensitive. For interactive, sub-second code execution inside an agent request, sandboxes are faster and simpler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nsjail / gVisor (DIY)
&lt;/h3&gt;

&lt;p&gt;Security-focused teams sometimes build custom sandboxes using gVisor (Google's container sandbox kernel, also used by Cloud Run itself) or nsjail (a Linux namespacing tool). These are powerful but require deep Linux security expertise to configure correctly; seccomp profiles, namespace configuration, capability dropping and are effectively engineering projects in their own right. Cloud Run Sandboxes encapsulate this complexity behind a single CLI command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current limitations to know
&lt;/h2&gt;

&lt;p&gt;Cloud Run Sandboxes are in &lt;strong&gt;public preview&lt;/strong&gt; as of July 2026. This means they are subject to the pre-GA terms, available as-is, with potentially limited support, and subject to change before GA (General Availability).&lt;/p&gt;

&lt;p&gt;Practical limitations to factor into your architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Preview status.&lt;/strong&gt; Do not build a production-critical system that cannot function without this feature until GA is announced. The API may change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource sharing.&lt;/strong&gt; Sandboxes share the CPU and memory of your Cloud Run instance. A sandbox running computationally intensive code will consume resources from your service's allocated capacity. Size your instances accordingly when sandbox workloads are CPU or memory intensive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No persistent state.&lt;/strong&gt; Everything written inside a sandbox is discarded unless explicitly exported via &lt;code&gt;--export-tar&lt;/code&gt;. Design your agent to treat sandbox execution as stateless.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeout enforcement.&lt;/strong&gt; Your subprocess call's &lt;code&gt;timeout&lt;/code&gt; parameter is what kills a runaway sandbox, there is no automatic execution time limit enforced by the platform independent of your code. Always set a timeout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language support.&lt;/strong&gt; The sandbox can run any language installed in your container image. Python, Node.js, Go, Ruby, and bash are all available if they are present in your Dockerfile. There is no built-in multi-language runtime, you provision what you need.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Get started today
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Enable the API if not already enabled&lt;/span&gt;
gcloud services &lt;span class="nb"&gt;enable &lt;/span&gt;run.googleapis.com

&lt;span class="c"&gt;# Deploy your first sandbox-enabled service&lt;/span&gt;
gcloud beta run deploy my-sandbox-agent &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gcr.io/my-project/agent:latest &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;africa-south1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--sandbox-launcher&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allow-unauthenticated&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min-instances&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1

&lt;span class="c"&gt;# Test it with a simple curl&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://YOUR_SERVICE_URL/execute &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"code": "print(1 + 1)"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full documentation, quickstart samples, and the ADK integration guide are at &lt;a href="https://docs.cloud.google.com/run/docs/code-execution" rel="noopener noreferrer"&gt;docs.cloud.google.com/run/docs/code-execution&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The broader picture
&lt;/h2&gt;

&lt;p&gt;Cloud Run Sandboxes land at a specific moment in AI engineering history. The question of how to safely let AI systems execute code, whether that means a Gemini model writing a Python script to analyse a spreadsheet, or an autonomous agent spinning up a browser to complete a research task; is one of the hardest practical problems in building production AI applications.&lt;/p&gt;

&lt;p&gt;Until recently, the industry's answer was, build your own sandboxing infrastructure, pay for a specialised third-party service, or accept the risk. None of these are satisfying answers for teams that want to ship fast and operate responsibly.&lt;/p&gt;

&lt;p&gt;Cloud Run Sandboxes offer a fourth answer, use the cloud infrastructure you already trust, with security boundaries designed for exactly this use case, at no additional cost. The 500ms sandbox startup time means this is practical for interactive agent workloads. The zero-trust-by-default credential isolation means the security model does not depend on your generated code being well-behaved.&lt;/p&gt;

&lt;p&gt;For teams building AI agents on GCP and the number of such teams is growing rapidly, this removes one of the last credible reasons to use an external sandbox service.&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>cloudrun</category>
      <category>gcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>Zero to Multi-Region: High Availability Serverless with Cloud Run and Cross-Region Failover &amp; Failback</title>
      <dc:creator>Caleb Duff</dc:creator>
      <pubDate>Fri, 24 Jul 2026 00:52:30 +0000</pubDate>
      <link>https://dev.to/gdg/zero-to-multi-region-high-availability-serverless-with-cloud-run-and-cross-region-failover--dcc</link>
      <guid>https://dev.to/gdg/zero-to-multi-region-high-availability-serverless-with-cloud-run-and-cross-region-failover--dcc</guid>
      <description>&lt;p&gt;Google just made multi-region Cloud Run significantly easier. Here is the full picture; what changed, what it means in practice, and how to build it right.&lt;/p&gt;

&lt;p&gt;Most teams discover they need multi-region architecture the hard way and  sadly, during an outage. Whether you're running a global e-commerce platform, a real-time gaming API, or a financial services application, users expect your service to be available whenever they need it. There is a conversation that happens in almost every engineering team at some point. It usually starts with a post-mortem. A regional Google Cloud outage or a Cloud Run service that hit a cold start spike, or a single-region deployment that could not handle the latency demands of users spread across Lagos, Nairobi, and London simultaneously, caused enough pain that someone finally asked: &lt;em&gt;why are we only deployed in one region?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The answer is usually one of three things: it felt complex, it felt expensive, or no one had prioritised it yet.&lt;/p&gt;

&lt;p&gt;In July 2026, Google moved Cloud Run &lt;strong&gt;Service Health&lt;/strong&gt; to General Availability and the timing was hard to miss. Six days earlier, a power cut at Google's Netherlands data centre had knocked three services offline. The GA release brings automatic cross-region failover to Cloud Run with what Google describes as a two-step setup: add a readiness probe, set minimum instances to at least 1. The load balancer does the rest.&lt;/p&gt;

&lt;p&gt;This article covers the full architecture, what Service Health is, how readiness probes underpin it, how to set up the Global Load Balancer correctly, and how to test that failover actually works. It also covers the production details.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed: Service Health and readiness probes
&lt;/h2&gt;

&lt;p&gt;Before Service Health, multi-region Cloud Run required you to implement a &lt;code&gt;/health&lt;/code&gt; endpoint in your application and configure a separate HTTPS health check at the load balancer level. This worked, but it had a significant gap. The load balancer's health check only knew whether the Cloud Run service &lt;em&gt;endpoint&lt;/em&gt; was responding, not whether the individual container instances behind it were actually ready to serve traffic.&lt;/p&gt;

&lt;p&gt;Service Health introduces two new capabilities that close this gap:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Readiness probes&lt;/strong&gt; operate at the container instance level. Cloud Run periodically sends an HTTP request to a path you specify on each running container instance. If the probe fails, Cloud Run stops routing requests to that instance until the probe succeeds again. Critically, a failing readiness probe does not kill the instance (that is what a liveness probe does), it simply marks the instance as not ready for traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Health&lt;/strong&gt; aggregates the readiness state of all container instances in a region into a single regional health signal. This aggregated health status is exposed through the Serverless NEGs (Network Endpoint Groups) for that region. When the Global Load Balancer reads the NEG's health status and sees a region is unhealthy, because enough instances are failing their readiness probes; it automatically reroutes traffic to a healthy region. When the failing region recovers, traffic is gradually restored without any operator action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result:&lt;/strong&gt; failover and failback capabilities are now fully automated, triggered by real instance-level health rather than a synthetic endpoint check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Container instance (readiness probe fails)
        │
        ▼
Cloud Run aggregates probe results across all instances in the region to determine the overall health status of each regional service
        │
        ▼
Service Health: region marked UNHEALTHY
        │
        ▼
Serverless NEG reports unhealthy status to Global Load Balancer
        │
        ▼
Load Balancer stops routing to this region → shifts traffic to healthy region
        │
        ▼
Region recovers → Load Balancer gradually restores traffic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is available in all Cloud Run regions at no extra charge beyond the CPU and memory consumed while readiness probes run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌──────────────────────────────────┐
                    │   Global Anycast IP (single IP)  │
                    │   + SSL Certificate (managed)    │
                    └───────────────┬──────────────────┘
                                    │
                    ┌───────────────▼──────────────────┐
                    │  Global External HTTP(S) LB      │
                    │  (URL map + forwarding rules)    │
                    └──────┬──────────────────┬────────┘
                           │                  │
        ┌──────────────────▼──┐         ┌─────▼──────────────────┐
        │  Serverless NEG     │         │  Serverless NEG        │
        │  africa-south1      │         │  us-central1           │
        │  (Service Health    │         │  (Service Health       │
        │   status: healthy)  │         │   status: healthy)     │
        └──────────┬──────────┘         └───────────┬────────────┘
                   │                                │
   ┌───────────────▼───────────┐     ┌──────────────▼──────────────┐
   │  Cloud Run Service        │     │  Cloud Run Service          │
   │  africa-south1            │     │  us-central1                │
   │  Readiness probe: /health │     │  Readiness probe: /health   │
   │  min-instances: 1+        │     │  min-instances: 1+          │
   │  (auto-scales 0–N)        │     │  (auto-scales 0–N)          │
   └───────────────────────────┘     └─────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Prerequisites and setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-project-id"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PROJECT_NUMBER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud projects describe &lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"value(projectNumber)"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SERVICE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"my-api"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION_A&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"africa-south1"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;REGION_B&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-central1"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"api.yourdomain.com"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;IMAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"gcr.io/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SERVICE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:latest"&lt;/span&gt;

gcloud config &lt;span class="nb"&gt;set &lt;/span&gt;project &lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt;

&lt;span class="c"&gt;# Enable required APIs&lt;/span&gt;
gcloud services &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  run.googleapis.com &lt;span class="se"&gt;\&lt;/span&gt;
  compute.googleapis.com &lt;span class="se"&gt;\&lt;/span&gt;
  artifactregistry.googleapis.com &lt;span class="se"&gt;\&lt;/span&gt;
  cloudbuild.googleapis.com &lt;span class="se"&gt;\&lt;/span&gt;
  networkservices.googleapis.com

&lt;span class="c"&gt;# Grant Cloud Build service account the Cloud Run builder role&lt;/span&gt;
gcloud projects add-iam-policy-binding &lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"serviceAccount:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_NUMBER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-   compute@developer.gserviceaccount.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"roles/run.builder"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: Implement the readiness probe endpoint
&lt;/h2&gt;

&lt;p&gt;The first step and the most important one for Service Health to work, is adding a readiness probe endpoint to your application. Unlike the previous/alternative approach where the &lt;code&gt;/health&lt;/code&gt; endpoint was for the load balancer's benefit, this endpoint is called directly by Cloud Run on each container instance to determine per-instance readiness.&lt;/p&gt;

&lt;p&gt;Two rules from the official docs that matter here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use an HTTP/1 endpoint (the Cloud Run default, not HTTP/2)&lt;/li&gt;
&lt;li&gt;The endpoint path must match the &lt;code&gt;path&lt;/code&gt; in your probe configuration exactly
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Node.js / Express&lt;/span&gt;
&lt;span class="c1"&gt;// Lightweight — no DB calls, no downstream dependencies&lt;/span&gt;
&lt;span class="c1"&gt;// This runs frequently on every instance&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/health&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;healthy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REGION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// If you want the probe to reflect actual readiness&lt;/span&gt;
&lt;span class="c1"&gt;// (e.g. connection pool initialised), you can check internal state:&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isReady&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/health&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isReady&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not_ready&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;healthy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Set isReady = true after your startup tasks complete&lt;/span&gt;
&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isReady&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python / FastAPI
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;is_ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/health&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;readiness_probe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_ready&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not_ready&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;healthy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;region&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;REGION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@app.on_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;startup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;startup_event&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;is_ready&lt;/span&gt;
    &lt;span class="c1"&gt;# Initialise connections, warm caches, etc.
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;init_database_pool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;is_ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;is_ready&lt;/code&gt; pattern is the key upgrade over a basic &lt;code&gt;/health&lt;/code&gt; endpoint. The readiness probe on each instance will return 503 until your startup tasks complete, preventing the load balancer from routing traffic to an instance that is running but not yet ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Deploy to multiple regions with readiness probes
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;gcloud run deploy&lt;/code&gt; supports deploying to multiple regions in a single command, and the &lt;code&gt;--readiness-probe&lt;/code&gt; flag attaches the probe configuration at deploy time. Failovers require at least two (2) services from different regions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Deploy to both regions simultaneously with readiness probe&lt;/span&gt;
gcloud run deploy &lt;span class="nv"&gt;$SERVICE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--regions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt;,&lt;span class="nv"&gt;$REGION_B&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--max-instances&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--concurrency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cpu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;512Mi &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30s &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--readiness-probe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"httpGet.path=/health"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set-env-vars&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ENV=production"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allow-unauthenticated&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--readiness-probe="httpGet.path=/health"&lt;/code&gt; flag is the new way to configure probes at deploy time. You can also configure additional probe parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Full readiness probe configuration&lt;/span&gt;
gcloud run deploy &lt;span class="nv"&gt;$SERVICE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--regions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt;,&lt;span class="nv"&gt;$REGION_B&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--readiness-probe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"httpGet.path=/health,periodSeconds=10,failureThreshold=3,successThreshold=1,timeoutSeconds=5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or via YAML service definition (the Terraform-friendly approach):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# service.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;serving.knative.dev/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-api&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;autoscaling.knative.dev/minScale&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
        &lt;span class="na"&gt;autoscaling.knative.dev/maxScale&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;100"&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcr.io/PROJECT_ID/my-api:latest&lt;/span&gt;
        &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;512Mi&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ENV&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
        &lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/health&lt;/span&gt;
          &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
          &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
          &lt;span class="na"&gt;successThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
          &lt;span class="na"&gt;timeoutSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
        &lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/health&lt;/span&gt;
          &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
          &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The difference between readiness and liveness probes
&lt;/h3&gt;

&lt;p&gt;Both probe types are supported on Cloud Run. Understanding the distinction is critical:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Readiness probe failure:&lt;/strong&gt; Cloud Run stops routing requests to that instance. The instance continues running. Once the probe succeeds again, routing resumes. Service Health aggregates these to determine regional health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Liveness probe failure:&lt;/strong&gt; Cloud Run restarts the container instance. Use liveness probes for detecting deadlocks or unrecoverable stuck states.&lt;/p&gt;

&lt;p&gt;For Service Health's automatic failover, readiness probes are what matter. Liveness probes are a complement, they handle instance-level recovery, while readiness probes handle traffic routing decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Set up the global external Application Load Balancer
&lt;/h2&gt;

&lt;p&gt;With the new Service Health model, the load balancer configuration is simpler than before, you no longer need to configure a separate HTTPS health check at the load balancer level. Service Health exposes regional health through the Serverless NEG itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the backend service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Single backend service, both regions are added as NEG backends&lt;/span&gt;
gcloud compute backend-services create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-bs&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--load-balancing-scheme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EXTERNAL_MANAGED &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: unlike the earlier approach with separate backend services per region, Service Health works with a &lt;strong&gt;single backend service&lt;/strong&gt; that has multiple regional NEG backends. The load balancer reads health from each NEG and routes accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reserve a global static IP (Set up a global static external IP address to reach your load balancer:)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud compute addresses create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-ip&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;PREMIUM &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ip-version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;IPV4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GLOBAL_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud compute addresses describe &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-ip&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"get(address)"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Global IP: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLOBAL_IP&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# → Update your DNS A record to this IP before proceeding&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create URL map, proxy, and forwarding rules
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a URL map to route incoming requests to the backend service:&lt;/span&gt;
gcloud compute url-maps create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-lb&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--default-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-bs&lt;/span&gt;

&lt;span class="c"&gt;# For HTTPS (recommended for production):&lt;/span&gt;
&lt;span class="c"&gt;# Create Google-managed SSL certificate&lt;/span&gt;
gcloud compute ssl-certificates create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-ssl&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--domains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$DOMAIN&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt;

&lt;span class="c"&gt;# Create the target HTTPS proxy to route requests to your URL map:&lt;/span&gt;
gcloud compute target-https-proxies create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-https-proxy&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url-map&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-lb&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ssl-certificates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-ssl&lt;/span&gt;

&lt;span class="c"&gt;# Create the HTTPS forwarding rule  to route incoming requests to the proxy:&lt;/span&gt;
gcloud compute forwarding-rules create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-https-fr&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--load-balancing-scheme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EXTERNAL_MANAGED &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;PREMIUM &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-ip&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-https-proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-https-proxy&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ports&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;443

&lt;span class="c"&gt;# HTTP forwarding rule (redirect to HTTPS)&lt;/span&gt;
gcloud compute target-http-proxies create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-http-proxy&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url-map&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-lb&lt;/span&gt;

gcloud compute forwarding-rules create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-http-fr&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--load-balancing-scheme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EXTERNAL_MANAGED &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;PREMIUM &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-ip&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target-http-proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-http-proxy&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ports&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Create Serverless NEGs and attach them
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Serverless NEG for africa-south1&lt;/span&gt;
gcloud compute network-endpoint-groups create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-neg-&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-endpoint-type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;serverless &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cloud-run-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;

&lt;span class="c"&gt;# Serverless NEG for us-central1&lt;/span&gt;
gcloud compute network-endpoint-groups create &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-neg-&lt;/span&gt;&lt;span class="nv"&gt;$REGION_B&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_B&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-endpoint-type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;serverless &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cloud-run-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;

&lt;span class="c"&gt;# Add both NEGs to the single backend service&lt;/span&gt;
gcloud compute backend-services add-backend &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-bs&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-endpoint-group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-neg-&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-endpoint-group-region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt;

gcloud compute backend-services add-backend &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-bs&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-endpoint-group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-neg-&lt;/span&gt;&lt;span class="nv"&gt;$REGION_B&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network-endpoint-group-region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, Service Health is active. Cloud Run is running readiness probes on every instance in both regions, aggregating the results into a regional health signal, and the load balancer reads that signal via the Serverless NEGs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Monitor Service Health with Cloud Monitoring
&lt;/h2&gt;

&lt;p&gt;Service Health exposes two metrics through Cloud Monitoring that you should track from day one:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;run.googleapis.com/container/instance_count_with_readiness&lt;/code&gt;&lt;/strong&gt;, the number of instances passing their readiness probe per region. Watch this metric to see the health state of your instance pool in each region in real time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;run.googleapis.com/service_health_count&lt;/code&gt;&lt;/strong&gt;, the regional Cloud Run service health as reported to the load balancer. Possible values: &lt;code&gt;HEALTHY&lt;/code&gt;, &lt;code&gt;UNHEALTHY&lt;/code&gt;, &lt;code&gt;UNKNOWN&lt;/code&gt;. The load balancer uses this to make failover decisions. &lt;code&gt;UNKNOWN&lt;/code&gt; is reported until the service has enough data from probes to determine health, typically within the first few minutes of deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# View current service health status via gcloud&lt;/span&gt;
gcloud run services describe &lt;span class="nv"&gt;$SERVICE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"value(status.conditions)"&lt;/span&gt;

&lt;span class="c"&gt;# Or check via the Console:&lt;/span&gt;
&lt;span class="c"&gt;# Cloud Run → your service → Metrics tab → "Instance count with readiness"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set up an alerting policy that fires when &lt;code&gt;service_health_count&lt;/code&gt; for any region transitions to &lt;code&gt;UNHEALTHY&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# alert-policy.yaml&lt;/span&gt;
&lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cloud&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;region&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;unhealthy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;—&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;failover&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;active"&lt;/span&gt;
&lt;span class="na"&gt;conditions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Service&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;health&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;UNHEALTHY"&lt;/span&gt;
  &lt;span class="na"&gt;conditionThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;resource.type="cloud_run_revision"&lt;/span&gt;
      &lt;span class="s"&gt;metric.type="run.googleapis.com/service_health_count"&lt;/span&gt;
      &lt;span class="s"&gt;metric.labels.health_status="UNHEALTHY"&lt;/span&gt;
    &lt;span class="na"&gt;comparison&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;COMPARISON_GT&lt;/span&gt;
    &lt;span class="na"&gt;thresholdValue&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;60s&lt;/span&gt;
    &lt;span class="na"&gt;aggregations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;alignmentPeriod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;60s&lt;/span&gt;
      &lt;span class="na"&gt;perSeriesAligner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ALIGN_MAX&lt;/span&gt;
&lt;span class="na"&gt;notificationChannels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;projects/${PROJECT_ID}/notificationChannels/YOUR_CHANNEL_ID&lt;/span&gt;
&lt;span class="na"&gt;documentation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;A Cloud Run region has become unhealthy and traffic is being&lt;/span&gt;
    &lt;span class="s"&gt;rerouted to the remaining healthy region(s). Investigate the&lt;/span&gt;
    &lt;span class="s"&gt;failing region's logs and instance readiness metrics immediately.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Testing failover
&lt;/h2&gt;

&lt;p&gt;Testing is not optional, it is the only way to know your failover actually works before your users discover it during a real incident.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 1: Use the sample application's toggle (for the official sample)
&lt;/h3&gt;

&lt;p&gt;The Google Cloud sample application (&lt;code&gt;golang-samples/run/service-health&lt;/code&gt;) includes a built-in toggle button in its UI that marks a region as unhealthy. For production applications, use Method 2.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 2: Force readiness probe failure via environment variable
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Redeploy africa-south1 with a flag that makes /health return 503&lt;/span&gt;
gcloud run deploy &lt;span class="nv"&gt;$SERVICE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set-env-vars&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"FORCE_UNHEALTHY=true,ENV=production"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your application, check this variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/health&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FORCE_UNHEALTHY&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;forced_unhealthy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;healthy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observe the failover sequence
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get load balancer IP&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LBIP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud compute addresses describe &lt;span class="nv"&gt;$SERVICE&lt;/span&gt;&lt;span class="nt"&gt;-ip&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'value(address)'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Continuous requests — watch region shift in responses&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;RESPONSE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOMAIN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/health&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="s1"&gt;'+%H:%M:%S'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; — &lt;/span&gt;&lt;span class="nv"&gt;$RESPONSE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;sleep &lt;/span&gt;2
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should observe:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Requests showing &lt;code&gt;"region": "africa-south1"&lt;/code&gt; — normal operation&lt;/li&gt;
&lt;li&gt;A mix of responses as the probe failure propagates across instances&lt;/li&gt;
&lt;li&gt;All requests showing &lt;code&gt;"region": "us-central1"&lt;/code&gt; — failover complete&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;service_health_count&lt;/code&gt; metric for &lt;code&gt;africa-south1&lt;/code&gt; showing &lt;code&gt;UNHEALTHY&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Restore the region:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud run deploy &lt;span class="nv"&gt;$SERVICE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set-env-vars&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ENV=production"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Traffic gradually returns to &lt;code&gt;africa-south1&lt;/code&gt; as instances pass their readiness probes and Service Health transitions back to &lt;code&gt;HEALTHY&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safe rollout strategy using readiness probes
&lt;/h2&gt;

&lt;p&gt;One of the most powerful features of the new readiness probe model is the ability to do &lt;strong&gt;canary deployments across regions&lt;/strong&gt; with automatic rollback via Service Health.&lt;/p&gt;

&lt;p&gt;The official recommended rollout process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Step 1: Deploy new revision to ONE region with 1% traffic&lt;/span&gt;
gcloud run deploy &lt;span class="nv"&gt;$SERVICE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_NEW&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--readiness-probe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"httpGet.path=/health"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--no-traffic&lt;/span&gt;  &lt;span class="c"&gt;# Deploy but send no traffic yet&lt;/span&gt;

&lt;span class="c"&gt;# Step 2: Send 1% of traffic to new revision in REGION_A only&lt;/span&gt;
gcloud run services update-traffic &lt;span class="nv"&gt;$SERVICE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--to-revisions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;LATEST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1

&lt;span class="c"&gt;# Step 3: Monitor readiness metric&lt;/span&gt;
&lt;span class="c"&gt;# run.googleapis.com/container/instance_count_with_readiness&lt;/span&gt;
&lt;span class="c"&gt;# If this stays healthy, continue increasing traffic&lt;/span&gt;

&lt;span class="c"&gt;# Step 4: Ramp to 100% in REGION_A&lt;/span&gt;
gcloud run services update-traffic &lt;span class="nv"&gt;$SERVICE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_A&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--to-revisions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;LATEST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;100

&lt;span class="c"&gt;# Step 5: Once REGION_A service_health_count is stable HEALTHY,&lt;/span&gt;
&lt;span class="c"&gt;# deploy to REGION_B&lt;/span&gt;
gcloud run deploy &lt;span class="nv"&gt;$SERVICE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$IMAGE_NEW&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$REGION_B&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--readiness-probe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"httpGet.path=/health"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the new revision's readiness probes fail in &lt;code&gt;REGION_A&lt;/code&gt;, Service Health marks that region unhealthy, the load balancer routes traffic to &lt;code&gt;REGION_B&lt;/code&gt; (still running the old revision), and you have automatic rollback without a single manual step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Known limitations of Service Health (GA)
&lt;/h2&gt;

&lt;p&gt;The official documentation lists several limitations worth knowing before you build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minimum instances required.&lt;/strong&gt; You must configure at least one minimum instance per region for Service Health to calculate health. A region with zero running instances cannot report health, which means a cold-start region cannot participate in automatic failover.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimum two regions.&lt;/strong&gt; Failover requires at least two services from different regions. If you only deploy to one region and it fails, the load balancer returns &lt;code&gt;no healthy upstream&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Max 5 NEG backends for cross-region internal LB.&lt;/strong&gt; The limitation applies to the internal load balancer variant, not the global external LB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No URL masks or tags in Serverless NEGs.&lt;/strong&gt; If your routing requires URL masks, you cannot use Service Health's NEG model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No IAP from the backend service.&lt;/strong&gt; If you need Identity-Aware Proxy, configure it directly on the Cloud Run service, not at the load balancer backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First probe on new instances.&lt;/strong&gt; A newly started instance will not have its first readiness probe counted before it begins receiving traffic. This means a very brief window where traffic may route to an instance before it has confirmed readiness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revisions without probes are treated as unknown.&lt;/strong&gt; The load balancer treats unknown health as healthy, so if you deploy a revision without a readiness probe configured, it will receive traffic regardless.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last two points are important for zero-downtime deployments. The recommended safe rollout process (canary in one region before the other) directly addresses both.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this architecture does not solve
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Database availability.&lt;/strong&gt; Compute-layer failover is irrelevant if your Cloud Run service connects to a single-region Cloud SQL instance. The database tier needs its own HA: Cloud SQL cross-region read replicas, Cloud Spanner for global consistency, or Firestore in Native mode (inherently multi-region).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stateful sessions.&lt;/strong&gt; Cloud Run is stateless. Cross-region routing will invalidate in-memory sessions. Use Cloud Memorystore (Redis) or stateless JWT-based sessions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data residency.&lt;/strong&gt; Routing traffic across regions may conflict with NDPR, GDPR, or sector-specific regulations. Know your data residency obligations before deploying multi-region.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pub/Sub push subscriptions.&lt;/strong&gt; By default, Pub/Sub delivers messages to push endpoints in the same region where it stores the messages. A multi-region Cloud Run setup behind a global LB does not automatically receive Pub/Sub push traffic from all regions. The official docs provide a workaround, review the Pub/Sub multi-region push documentation before building event-driven architectures on this pattern.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>cloudrun</category>
      <category>googlecloud</category>
      <category>gcp</category>
    </item>
    <item>
      <title>Mastering the T: How to Balance Breadth and Depth in Tech. [T-Shaped Engineer]</title>
      <dc:creator>Caleb Duff</dc:creator>
      <pubDate>Tue, 03 Feb 2026 17:13:01 +0000</pubDate>
      <link>https://dev.to/duffigoogle/mastering-the-t-how-to-balance-breadth-and-depth-in-tech-t-shaped-engineer-3plb</link>
      <guid>https://dev.to/duffigoogle/mastering-the-t-how-to-balance-breadth-and-depth-in-tech-t-shaped-engineer-3plb</guid>
      <description>&lt;p&gt;For decades, the tech industry has argued over a classic dilemma: Is it better to be a Specialist (the master of one) or a Generalist (the jack of all trades)? I remember asking my tech tutor this question some years ago.&lt;/p&gt;

&lt;p&gt;On one hand, we have the "I-shaped" developer (depth-full techie). They know everything there is to know about PostgreSQL or low-level C++, but they struggle to deploy their own code or understand the frontend UI. On the other hand, you have the "Dash-shaped" generalist. They can dabble in everything, but they lack the depth to solve complex, scaling problems.&lt;br&gt;
In modern software engineering, neither is quite enough. The silos are breaking down. DevOps, Frontend, Backend, and Product are merging into cross-functional squads.&lt;/p&gt;

&lt;p&gt;Let's talk about the *&lt;em&gt;**T&lt;/em&gt;&lt;em&gt;-Shaped Engineer&lt;/em&gt;*.&lt;br&gt;
This concept isn’t new (at least for me), but in the age of AI and rapid product iteration, it has become the gold standard for employability and career growth. Here is what I know it means, and why you should strive to be one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Anatomy of the "&lt;/strong&gt;T*&lt;em&gt;"&lt;/em&gt;*&lt;br&gt;
This concept is a metaphor for your skills profile, composed of two bars:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjddgj9zfsv6nejdg5p5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjddgj9zfsv6nejdg5p5d.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;i. The Vertical Bar (Depth)&lt;br&gt;
This represents your deep expertise. It is the core skill that gets you hired.&lt;br&gt;
&lt;strong&gt;Check this out:&lt;/strong&gt; You are a Senior React Developer. You know the virtual DOM inside out, you understand state management patterns, and you can optimize rendering performance in your sleep.&lt;br&gt;
&lt;strong&gt;Why you need it:&lt;/strong&gt; Without depth, you cannot solve hard problems. You need a foundation where you are the "go-to" person.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ii. The Horizontal Bar (Breadth)&lt;/strong&gt;&lt;br&gt;
This represents your ability to collaborate across disciplines. It’s not about being an expert in everything; it’s about knowing enough to be dangerous and equally helpful.&lt;br&gt;
&lt;strong&gt;Check this out:&lt;/strong&gt; Even though you are a React pro as I have sighted above, you understand how a REST API is structured. You know the basics of Docker. You understand UX design principles. You have "soft skills" like communication and empathy.&lt;br&gt;
&lt;strong&gt;Why you need it:&lt;/strong&gt; This allows you to speak the same language as the rest of your team. It prevents you from being blocked when a minor issue arises outside your core domain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why **T&lt;/strong&gt;-Shaped Developers Win**&lt;br&gt;
&lt;strong&gt;i. They Break Down Silos&lt;/strong&gt;&lt;br&gt;
An "&lt;strong&gt;I&lt;/strong&gt;-shaped" backend developer writes an API and throws it over the wall to the frontend team. If it breaks, they say, "It works on my machine."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0y8s1hal8m58pq2qzbqm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0y8s1hal8m58pq2qzbqm.png" alt=" " width="800" height="713"&gt;&lt;/a&gt;&lt;br&gt;
A &lt;strong&gt;T-shaped&lt;/strong&gt; backend developer understands how the frontend consumes data. They might even tweak the JSON structure to make the frontend developer’s life easier. They bridge gaps rather than creating them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ii. They Are Adaptive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8xjim9nz1hxlxyfpouu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8xjim9nz1hxlxyfpouu.png" alt=" " width="800" height="737"&gt;&lt;/a&gt;&lt;br&gt;
Technology changes fast. If your entire career is built on a single framework that goes obsolete (RIP Flash), you’re in trouble. &lt;br&gt;
Because T-shaped developers have a broad base of general knowledge, they can pivot easier. They have "&lt;strong&gt;learned how to learn.&lt;/strong&gt;"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iii. They Make Better Architects&lt;/strong&gt;&lt;br&gt;
You cannot design a scalable system if you don't understand how the database affects the UI, or how the deployment pipeline affects testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;T-shaped engineers see the "Big Picture.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;How to Build Your Own "T"&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Note:&lt;/strong&gt; Becoming T-shaped doesn't happen overnight. It is a deliberate career strategy. Here is a roadmap I will share with you:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1&lt;/strong&gt;: Drill Deep (Build the Vertical)&lt;br&gt;
Early in your career, focus on mastery. Pick a stack (e.g., Python/Django or Java/Spring or Swift) and get really, really good at it. You need to build your confidence and value first. With this you can provide &lt;strong&gt;business-value&lt;/strong&gt; to yourself, your team or employer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2:&lt;/strong&gt; Scan the Periphery (Build the Horizontal)&lt;br&gt;
Once you are comfortable in your core, look at the technologies immediately adjacent to you (&lt;em&gt;very important&lt;/em&gt;).&lt;br&gt;
Are you a backend dev? Learn basic CSS and how a browser renders a page.&lt;br&gt;
Or a frontend dev? Learn how to set up a basic CI/CD pipeline or write a SQL query.&lt;/p&gt;

&lt;p&gt;An Engineer? Learn the basics of Product Management and Business logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 3:&lt;/strong&gt; Cultivate Empathy&lt;br&gt;
The horizontal bar isn't just code; it's people. Understanding what stresses out your Project Manager or what constraints your Designer is working under makes you a better engineer. Empathy is a technical skill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Evolution: From **T&lt;/strong&gt; to &lt;strong&gt;Pi&lt;/strong&gt; (&lt;strong&gt;π&lt;/strong&gt;)**&lt;br&gt;
Once you master the T-shape, the journey isn't over. Many senior engineers eventually become &lt;strong&gt;Pi-shaped (π)&lt;/strong&gt;. This means they have a broad base of knowledge and two deep spikes of expertise (e.g., Expert in Backend Go and Expert in Cloud Infrastructure).&lt;/p&gt;

&lt;p&gt;The era of the solitary genius coding in a dark room is ending. Modern software is a team sport that somehow has AI as a need member.&lt;br&gt;
You don't need to know everything. But you do need to be an expert in one  thing, and curious about everything else. By becoming a T-shaped engineer, you not only future-proof your career, but you also become the kind of teammate everyone wants to work with.&lt;br&gt;
So, look at your skillset today. You have the depth—now, where can you stretch your width?&lt;/p&gt;

</description>
      <category>specilization</category>
      <category>technology</category>
      <category>techie</category>
    </item>
  </channel>
</rss>
