<?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: Rajesh Yadav</title>
    <description>The latest articles on DEV Community by Rajesh Yadav (@rajesh_yadav_devops).</description>
    <link>https://dev.to/rajesh_yadav_devops</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%2F4190487%2F83b873d7-52fa-4218-bcc2-f5fcf54f95a1.png</url>
      <title>DEV Community: Rajesh Yadav</title>
      <link>https://dev.to/rajesh_yadav_devops</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rajesh_yadav_devops"/>
    <language>en</language>
    <item>
      <title>How to deploy an AI assistant: Pattern 2, the control/data split (customer cloud)</title>
      <dc:creator>Rajesh Yadav</dc:creator>
      <pubDate>Tue, 03 Nov 2026 05:21:35 +0000</pubDate>
      <link>https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-2-the-controldata-split-customer-cloud-4mf9</link>
      <guid>https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-2-the-controldata-split-customer-cloud-4mf9</guid>
      <description>&lt;p&gt;&lt;em&gt;A reference architecture for running the data plane of an AI assistant in the customer's own cloud account, with the provider keeping only a control plane&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;This document describes the second of three deployment patterns for an AI assistant platform. It is written for architects and platform engineers whose customer, or whose own organisation, has said: &lt;strong&gt;"our documents, our search index and our encryption key stay in our cloud account, under a key we can revoke without asking anyone."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The structure is the same as Pattern 1: a one-picture architecture, the request flow, the components, use cases, design considerations, what crosses the boundary, and when to choose it. The design is independent of any product; the technologies named can be replaced.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terms used throughout.&lt;/strong&gt; The &lt;em&gt;provider&lt;/em&gt; is whoever builds and operates the platform software: a vendor, or an internal platform team. The &lt;em&gt;customer&lt;/em&gt; is the organisation whose users and data the platform serves. In this pattern the customer also operates most of the system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites.&lt;/strong&gt; On the customer's side: a cloud account, a Kubernetes service, managed Postgres and object storage, a key management service, and access to a cloud model provider in the chosen region. On the provider's side: a build pipeline that can sign artifacts and an OCI registry. The customer needs a team that can run Kubernetes and its supporting services in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three patterns at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Data lives in&lt;/th&gt;
&lt;th&gt;Operated by&lt;/th&gt;
&lt;th&gt;Crosses the boundary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Shared service&lt;/td&gt;
&lt;td&gt;the provider's account, inside a residency boundary&lt;/td&gt;
&lt;td&gt;the provider&lt;/td&gt;
&lt;td&gt;every user's traffic, inside the boundary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2. Control/data split (this document)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;the customer's cloud account&lt;/td&gt;
&lt;td&gt;the customer runs the data plane; the provider runs a control plane&lt;/td&gt;
&lt;td&gt;signed software in, optional health metadata out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Isolated site&lt;/td&gt;
&lt;td&gt;the customer's building&lt;/td&gt;
&lt;td&gt;the customer, everything&lt;/td&gt;
&lt;td&gt;two signed files in, one optional file out&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The three questions still decide: where does the data live, who operates it, what crosses the boundary. For this pattern the third question is the one to get right, and the next section shows why.&lt;/p&gt;




&lt;h2&gt;
  
  
  The design to avoid: split by component
&lt;/h2&gt;

&lt;p&gt;The obvious way to meet the customer's rule is to &lt;strong&gt;split by component&lt;/strong&gt;: move the pieces that store customer content into the customer's account and keep the rest.&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%2Fz0p0wfsxw3llxc45rhat.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%2Fz0p0wfsxw3llxc45rhat.png" alt="Figure 1. Not recommended: split by component. The provider's account (white) runs the edge, gateway, identity broker, Chat Gateway, a shared Orchestrator and the model. The customer's account (grey) runs the retrieval, connector and cache modules with their data and keys. One private link joins them. The ◆ markers show where customer content still crosses." width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The customer runs retrieval over their own vector store, a connector module that reaches their systems from inside their network, a cache, their documents bucket, Vault and a KMS key they can revoke. The provider reaches these over one private link with mutual TLS. Software is pull-only. Stored data never leaves the customer's account.&lt;/p&gt;

&lt;p&gt;Now trace one chat message and mark every arrow where customer content crosses an account boundary with ◆.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Crossing&lt;/th&gt;
&lt;th&gt;Why it exists&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;①&lt;/td&gt;
&lt;td&gt;The user's question travels through the provider's edge, gateway and Chat Gateway&lt;/td&gt;
&lt;td&gt;The entry point is the provider's&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;②&lt;/td&gt;
&lt;td&gt;Retrieved passages come back over the link&lt;/td&gt;
&lt;td&gt;The Orchestrator is the provider's&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;③&lt;/td&gt;
&lt;td&gt;Results from the customer's systems come back over the link&lt;/td&gt;
&lt;td&gt;Same reason&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;④&lt;/td&gt;
&lt;td&gt;The full prompt goes to the model in the provider's account&lt;/td&gt;
&lt;td&gt;The model is the provider's&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑤&lt;/td&gt;
&lt;td&gt;The streamed answer sits in the provider's Redis for about five minutes&lt;/td&gt;
&lt;td&gt;The Chat Gateway is the provider's&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Five crossings per question. None of them is a breach: each is encrypted, disclosed, inside the residency boundary and gone within minutes. But the design cannot support the sentence the customer wants: &lt;em&gt;"your data never reaches our account."&lt;/em&gt; Stored data does not; data in flight does, five times.&lt;/p&gt;

&lt;p&gt;Two rules follow, and they apply to any architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Mark every arrow where content crosses a boundary.&lt;/strong&gt; If you cannot draw it, you do not know it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Defensible" is the floor.&lt;/strong&gt; The useful question is whether the customer can verify the promise without trusting the provider.&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;The fix is to split by &lt;strong&gt;plane&lt;/strong&gt;, not by component.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;control plane&lt;/strong&gt; is everything that is the same for every customer and carries no content: building and signing software, publishing it, issuing licences, collecting health metadata, taking support requests. The provider keeps this.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;data plane&lt;/strong&gt; is everything that touches a user, a document, a system or a prompt: entry point, gateway, sign-in, chat, Orchestrator, tools and actions, retrieval, connectors, data, keys, and the model call. The customer runs all of it, in their account.&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%2Fcm45vmy0t6483l27d169.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%2Fcm45vmy0t6483l27d169.png" alt="Figure 2. Split by plane. The customer's boundary holds the entire data plane, including a model router that calls the customer's own cloud model providers. The provider keeps a release pipeline, a signed licence, an opt-in health dashboard and a support intake. Every arrow that crosses the boundary is opened by the customer." width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three things change. There is &lt;strong&gt;no connectivity link&lt;/strong&gt;, because there is nothing for the provider to reach, and the provider has no inbound path at all. &lt;strong&gt;The model call stays home&lt;/strong&gt;: the Orchestrator calls the customer's own cloud model providers in the customer's account, under the customer's contract. There is &lt;strong&gt;nothing to crypto-shred at exit&lt;/strong&gt;, because the provider holds no configuration, sessions or buffer. The ◆ marker appears nowhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Request flow
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hop&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Who opens it&lt;/th&gt;
&lt;th&gt;Authentication&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;①&lt;/td&gt;
&lt;td&gt;Client → customer edge&lt;/td&gt;
&lt;td&gt;HTTPS/443&lt;/td&gt;
&lt;td&gt;client&lt;/td&gt;
&lt;td&gt;opaque session cookie or token, resolved at the gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;②&lt;/td&gt;
&lt;td&gt;Edge → API gateway&lt;/td&gt;
&lt;td&gt;HTTPS/443&lt;/td&gt;
&lt;td&gt;load balancer&lt;/td&gt;
&lt;td&gt;n/a (network hop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;③&lt;/td&gt;
&lt;td&gt;Gateway → identity broker&lt;/td&gt;
&lt;td&gt;HTTPS/443&lt;/td&gt;
&lt;td&gt;gateway&lt;/td&gt;
&lt;td&gt;login and signing keys only; not on the chat path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;④&lt;/td&gt;
&lt;td&gt;Gateway → Chat Gateway&lt;/td&gt;
&lt;td&gt;HTTP/8080 over mTLS&lt;/td&gt;
&lt;td&gt;gateway&lt;/td&gt;
&lt;td&gt;mesh identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑤&lt;/td&gt;
&lt;td&gt;Chat Gateway → Orchestrator&lt;/td&gt;
&lt;td&gt;gRPC over mTLS&lt;/td&gt;
&lt;td&gt;Chat Gateway&lt;/td&gt;
&lt;td&gt;mesh identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑥&lt;/td&gt;
&lt;td&gt;Orchestrator → tools and actions&lt;/td&gt;
&lt;td&gt;gRPC / HTTPS over mTLS&lt;/td&gt;
&lt;td&gt;Orchestrator&lt;/td&gt;
&lt;td&gt;mTLS; the sandbox holds no credentials; per-user tokens from the vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑦&lt;/td&gt;
&lt;td&gt;Orchestrator → retrieval → pgvector&lt;/td&gt;
&lt;td&gt;gRPC; then Postgres/5432&lt;/td&gt;
&lt;td&gt;Orchestrator, then retrieval&lt;/td&gt;
&lt;td&gt;mTLS; database role from the customer's Vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑧&lt;/td&gt;
&lt;td&gt;Orchestrator → model router → customer's model providers&lt;/td&gt;
&lt;td&gt;HTTPS/443, private endpoint&lt;/td&gt;
&lt;td&gt;Orchestrator&lt;/td&gt;
&lt;td&gt;the customer's cloud identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑨&lt;/td&gt;
&lt;td&gt;Orchestrator → connector hub → customer systems&lt;/td&gt;
&lt;td&gt;gRPC; then HTTPS&lt;/td&gt;
&lt;td&gt;Orchestrator, then connector&lt;/td&gt;
&lt;td&gt;mTLS; connector credentials from Vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑩&lt;/td&gt;
&lt;td&gt;Streamed answer → Chat Gateway → user&lt;/td&gt;
&lt;td&gt;SSE over HTTPS&lt;/td&gt;
&lt;td&gt;already open&lt;/td&gt;
&lt;td&gt;same session as ①&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every hop stays inside the customer's boundary. The provider's column in the detailed topology has no live-request arrows at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Runs in&lt;/th&gt;
&lt;th&gt;Operated by&lt;/th&gt;
&lt;th&gt;Common choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Customer edge: domain, certificate, WAF, load balancer&lt;/td&gt;
&lt;td&gt;customer account&lt;/td&gt;
&lt;td&gt;customer&lt;/td&gt;
&lt;td&gt;cloud load balancer and WAF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API gateway, identity broker, identity provider&lt;/td&gt;
&lt;td&gt;customer account&lt;/td&gt;
&lt;td&gt;customer&lt;/td&gt;
&lt;td&gt;Kong, Keycloak, the customer's IdP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat Gateway, Orchestrator, retrieval, connector hub, Redis, mesh&lt;/td&gt;
&lt;td&gt;customer's Kubernetes cluster&lt;/td&gt;
&lt;td&gt;customer&lt;/td&gt;
&lt;td&gt;EKS, AKS or GKE; Istio or Linkerd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools and actions: sandbox, action gateway, tool connectors, per-user credential vault, metering&lt;/td&gt;
&lt;td&gt;customer account&lt;/td&gt;
&lt;td&gt;customer&lt;/td&gt;
&lt;td&gt;gVisor or Firecracker, MCP servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Postgres with pgvector, documents bucket, Vault, KMS key&lt;/td&gt;
&lt;td&gt;customer account&lt;/td&gt;
&lt;td&gt;customer&lt;/td&gt;
&lt;td&gt;managed Postgres, object storage, Vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model router and model accounts&lt;/td&gt;
&lt;td&gt;customer account, customer's contract&lt;/td&gt;
&lt;td&gt;customer&lt;/td&gt;
&lt;td&gt;Bedrock, Azure OpenAI, Vertex AI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivery: Argo CD, release gate, Kyverno, optional registry mirror&lt;/td&gt;
&lt;td&gt;customer account&lt;/td&gt;
&lt;td&gt;customer&lt;/td&gt;
&lt;td&gt;Argo CD, cosign, Kyverno&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability, egress proxy, audit, SIEM&lt;/td&gt;
&lt;td&gt;customer account&lt;/td&gt;
&lt;td&gt;customer&lt;/td&gt;
&lt;td&gt;OpenTelemetry stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Release pipeline, signing, OCI registry, signed licence&lt;/td&gt;
&lt;td&gt;provider&lt;/td&gt;
&lt;td&gt;provider&lt;/td&gt;
&lt;td&gt;GitHub Actions, cosign, Harbor or a cloud registry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Health dashboard (opt-in heartbeat), support intake&lt;/td&gt;
&lt;td&gt;provider&lt;/td&gt;
&lt;td&gt;provider&lt;/td&gt;
&lt;td&gt;Grafana&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A customer whose data must stay in their own cloud account
&lt;/h3&gt;

&lt;p&gt;The defining case. Documents, index and keys in the customer's account, encrypted under a key the customer can revoke, with no content in the provider's infrastructure. The customer can operate Kubernetes and its supporting services, or has a managed-service team that can.&lt;/p&gt;

&lt;h3&gt;
  
  
  A provider who must support several clouds
&lt;/h3&gt;

&lt;p&gt;Because the customer runs the data plane, the provider's software has to run on whichever cloud the customer uses. The design keeps every cloud-specific dependency behind an interface: the model router, the identity binding for the registry pull, and the key management.&lt;/p&gt;

&lt;h3&gt;
  
  
  A regulated business unit inside one company
&lt;/h3&gt;

&lt;p&gt;An internal platform team is the provider; a business unit with its own cloud account and its own compliance regime is the customer. The pull-only delivery and the egress proxy log give the business unit's auditors proof without trusting the platform team.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security and privacy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Delivery without access.&lt;/strong&gt; The provider never pushes anything. Its pipeline signs every chart and image, attaches an SBOM and a vulnerability-scan attestation, and publishes to an OCI registry. In the customer's cluster, Argo CD polls the registry over the customer's own outbound HTTPS and applies new versions; a release gate lets the customer review the SBOM and attestation first; Kyverno verifies the signature with a bundled, offline trust root before any pod starts. The customer holds every admin credential.&lt;/p&gt;

&lt;p&gt;For cross-cloud registry access, two methods work: federate the cluster's workload identity into a pull-only role at the provider, or issue a per-customer pull-only robot token the customer keeps in their own Vault. Both are scoped to that customer's repositories and can only pull.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identity inside the boundary.&lt;/strong&gt; The customer runs the identity broker, and the identity provider sits inside their boundary. The IdP token is verified once at login; after that the browser holds an opaque, hash-stored session. CLI tokens and API keys resolve the same way. No sign-in assertion crosses to the provider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools and actions in the customer's account.&lt;/strong&gt; The sandbox is self-hosted in the customer's account with no platform credentials and default-deny egress; a managed sandbox service would be a third party that sees content. The action gateway applies the customer's policy and approval steps. Tool connectors run against an allowlist the customer sets. Per-user tokens are sealed in a credential vault with a key id. Metering writes to a local store with limits per organisation and workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The model router points at the customer's own providers.&lt;/strong&gt; Several providers behind one interface, each in the customer's account, pinned to a region the customer chooses, reached over private endpoints, with invocation logging as the customer's own setting. The prompt never touches the provider's account. The nuance to state plainly: the model provider still sees prompts, under the customer's contract rather than the vendor's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data and authorization.&lt;/strong&gt; Postgres with pgvector, the documents bucket, Redis and Vault live in the customer's account. Authorization is one decision point: policy compiled into every query, with row-level security beneath it. Encryption uses a customer-owned KMS key. Revoke it and everything stops and becomes unreadable, including to provider support.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reliability
&lt;/h3&gt;

&lt;p&gt;High availability and disaster recovery are the customer's: multi-zone, a second region per their policy, immutable backups. The provider states no recovery targets here because there is no provider data plane to fail over. The provider commits only to registry availability, and an optional local registry mirror removes even that runtime dependency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operations
&lt;/h3&gt;

&lt;p&gt;Telemetry is local by default: Fluent Bit, OpenTelemetry, Loki, Jaeger, VictoriaMetrics, a local Grafana. Cloud and cluster audit logs stay in the account. The &lt;strong&gt;egress proxy log is the customer's proof&lt;/strong&gt;: it shows exactly two external names ever reached for the provider (the registry and, if opted in, the heartbeat), plus the customer's own model, identity and system endpoints.&lt;/p&gt;

&lt;p&gt;Support works two ways, both optional: a redacted support bundle the customer reads before sending, or a break-glass session the customer opens, approves, time-boxes and records in their own audit log. The break-glass session is the one path that could ever show content to the provider, and the diagram says so.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost
&lt;/h3&gt;

&lt;p&gt;The customer pays for the whole data plane: cluster, databases, model consumption under their own contract, a second region if they want one. Managed cloud services soften the operating cost but do not remove it. The provider's cost is small and fixed: a pipeline, a registry, a dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Model capacity, quota and regional placement are the customer's. The provider cannot add quota or fix an outage at the customer's model provider. Everything else scales as in Pattern 1, inside the customer's cluster.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design alternatives
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Split by component&lt;/strong&gt; (the first design above). Fewer things for the customer to run, but five content crossings per question.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A managed sandbox service.&lt;/strong&gt; Less to operate, but a third party that sees content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Push-based delivery&lt;/strong&gt; with a provider credential into the customer's cluster. Simpler for the provider, but gives it an inbound path, which this pattern exists to remove.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic heartbeat.&lt;/strong&gt; Useful for support, but it must stay opt-in and payload-free, or the egress proxy log stops being proof.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What crosses the boundary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Crossing&lt;/th&gt;
&lt;th&gt;Direction&lt;/th&gt;
&lt;th&gt;What travels&lt;/th&gt;
&lt;th&gt;Who opens it&lt;/th&gt;
&lt;th&gt;Can the customer switch it off?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Software pull&lt;/td&gt;
&lt;td&gt;customer → provider registry; software flows in&lt;/td&gt;
&lt;td&gt;signed charts, images, licence&lt;/td&gt;
&lt;td&gt;the customer's Argo CD and nodes&lt;/td&gt;
&lt;td&gt;yes; the running version keeps working, and a mirror removes the runtime dependency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heartbeat&lt;/td&gt;
&lt;td&gt;customer → provider&lt;/td&gt;
&lt;td&gt;versions, health, error counts; fixed schema, no payloads&lt;/td&gt;
&lt;td&gt;the customer's agent&lt;/td&gt;
&lt;td&gt;yes; opt-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support bundle&lt;/td&gt;
&lt;td&gt;customer → provider, manual&lt;/td&gt;
&lt;td&gt;redacted diagnostics the customer read first&lt;/td&gt;
&lt;td&gt;the customer&lt;/td&gt;
&lt;td&gt;yes; never required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Break-glass session&lt;/td&gt;
&lt;td&gt;customer opens; provider joins&lt;/td&gt;
&lt;td&gt;whatever the customer shows; nothing retained&lt;/td&gt;
&lt;td&gt;the customer&lt;/td&gt;
&lt;td&gt;yes; per incident, time-boxed, recorded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model call&lt;/td&gt;
&lt;td&gt;customer → &lt;em&gt;their own&lt;/em&gt; model provider&lt;/td&gt;
&lt;td&gt;prompt with retrieved passages&lt;/td&gt;
&lt;td&gt;the customer's Orchestrator&lt;/td&gt;
&lt;td&gt;it is the product; but it stays under the customer's account, contract and region&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Compare this with the first design's five content crossings per question. That comparison is the whole argument for splitting by plane.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The customer runs the whole data plane. This is close to the operating burden of an on-premises deployment, eased by managed cloud services.&lt;/li&gt;
&lt;li&gt;Support works half-blind: heartbeat and redacted bundles by default.&lt;/li&gt;
&lt;li&gt;Several model providers to support, with differences in models, limits and behaviour.&lt;/li&gt;
&lt;li&gt;No provider recovery targets. The provider commits only to registry availability.&lt;/li&gt;
&lt;li&gt;Version skew: N and N-1 are supported; a customer who stalls their release gate drifts out of the window.&lt;/li&gt;
&lt;li&gt;Not zero third parties. The customer's model provider still processes prompts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to choose this pattern
&lt;/h2&gt;

&lt;p&gt;Choose the control/data split when the customer's rule is &lt;strong&gt;"our documents, index and keys in our account, under a key we can revoke, and no content in your infrastructure"&lt;/strong&gt;, and they can operate Kubernetes and its supporting services. If they want the provider to run everything, Pattern 1. If not even a prompt may leave their building, Pattern 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment outline
&lt;/h2&gt;

&lt;p&gt;The provider prepares; the customer deploys.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Provider: release pipeline.&lt;/strong&gt; Build, sign every chart and image, attach the SBOM and scan attestation, publish to the OCI registry, issue the signed licence and a pull-only credential per customer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer: foundation.&lt;/strong&gt; Cloud account, network, Kubernetes cluster, managed Postgres with pgvector, object storage, Vault, a customer-owned KMS key, the model accounts with private endpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer: delivery path.&lt;/strong&gt; Argo CD pointed at the provider's registry over outbound HTTPS, the release gate, Kyverno with the bundled trust root, the optional registry mirror. Verify that the egress proxy log shows only the registry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer: identity and edge.&lt;/strong&gt; The identity broker inside the boundary, federated to the customer's identity provider; the customer's domain, certificate, WAF and load balancer; the API gateway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer: application and tools.&lt;/strong&gt; Argo CD applies the signed charts: Chat Gateway, Orchestrator, retrieval, connectors, mesh, the tools-and-actions layer, the model router configured for the customer's providers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer: observability and support.&lt;/strong&gt; Local telemetry, audit logs to the customer's SIEM, the opt-in heartbeat if wanted, the break-glass procedure written into the customer's runbook.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer: resilience.&lt;/strong&gt; High availability, a second region if policy requires it, immutable backups, and a test that revoking the KMS key stops everything as intended.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Detailed topology
&lt;/h2&gt;

&lt;p&gt;The full design in ten customer bands plus the provider's two control-plane bands. The hop numbers match the request flow table above. Open the figure at full size to read the component notes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/84ijtmlm0bs66b6zuwv1.png" rel="noopener noreferrer"&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%2Fg04jf2ucmkrahssk0wb3.png" alt="Figure 3. The full control/data split topology: clients, customer edge, gateway and identity, compute, tools and actions, data, model router, customer systems and HA/DR, pull-only delivery, and local observability, support and audit. The provider's column holds the release pipeline, licence, health dashboard and support intake." width="800" height="1547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This is part 2 of a three-part series. The other parts are also linked in the series box at the top of this article.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-1-the-shared-service-saas-4k6o"&gt;Pattern 1, the shared service (SaaS)&lt;/a&gt;: the provider runs everything inside a residency boundary.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-3-the-isolated-site-on-premises-and-air-gapped-259b"&gt;Pattern 3, the isolated site (on-premises and air-gapped)&lt;/a&gt;: everything runs in the customer's building, with models on local GPUs.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>ai</category>
      <category>kubernetes</category>
      <category>security</category>
    </item>
    <item>
      <title>How to deploy an AI assistant: Pattern 3, the isolated site (on-premises and air-gapped)</title>
      <dc:creator>Rajesh Yadav</dc:creator>
      <pubDate>Tue, 03 Nov 2026 05:12:53 +0000</pubDate>
      <link>https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-3-the-isolated-site-on-premises-and-air-gapped-259b</link>
      <guid>https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-3-the-isolated-site-on-premises-and-air-gapped-259b</guid>
      <description>&lt;p&gt;&lt;em&gt;A reference architecture for running the whole AI assistant platform, models included, inside the customer's own facility&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;This document describes the third of three deployment patterns for an AI assistant platform. It is written for architects and platform engineers whose customer, or whose own organisation, has said: &lt;strong&gt;"No prompt leaves this building. Not to a vendor, not to a cloud model provider, not to anyone. Our network has no route to the internet."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Defence, sovereign functions, regulated manufacturing, some banks and hospitals. Fewer organisations need this than the first two patterns, but the ones who ask for it will check.&lt;/p&gt;

&lt;p&gt;The structure is the same as Patterns 1 and 2. The design is independent of any product; the technologies named can be replaced.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terms used throughout.&lt;/strong&gt; The &lt;em&gt;provider&lt;/em&gt; is whoever builds and signs the platform software: a vendor, or an internal platform team. The &lt;em&gt;customer&lt;/em&gt; is the organisation whose facility the platform runs in. In this pattern the customer operates everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites.&lt;/strong&gt; A facility with its own network, GPU servers sized for peak inference, a Kubernetes distribution that can be installed offline, an internal certificate authority and time source, an approved process for carrying media in and out, and a team that can run Kubernetes, databases, Vault and GPUs without vendor access. A second data center if site-level recovery is required.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three patterns at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Data lives in&lt;/th&gt;
&lt;th&gt;Operated by&lt;/th&gt;
&lt;th&gt;Crosses the boundary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Shared service&lt;/td&gt;
&lt;td&gt;the provider's account, inside a residency boundary&lt;/td&gt;
&lt;td&gt;the provider&lt;/td&gt;
&lt;td&gt;every user's traffic, inside the boundary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Control/data split&lt;/td&gt;
&lt;td&gt;the customer's cloud account&lt;/td&gt;
&lt;td&gt;the customer runs the data plane; the provider runs a control plane&lt;/td&gt;
&lt;td&gt;signed software in, optional health metadata out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3. Isolated site (this document)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;the customer's building&lt;/td&gt;
&lt;td&gt;the customer, everything&lt;/td&gt;
&lt;td&gt;two signed files in, one optional file out&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For this pattern the three questions have short answers. The data lives in the building. The customer operates everything. Nothing crosses on an ordinary day. The rest of this document is what it takes to make those sentences true, and what it costs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&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%2Fj6n0unt775n2py60ugd9.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%2Fj6n0unt775n2py60ugd9.png" alt="Figure 1. The isolated site. One boundary around the customer's facility with a primary and a DR data center. Users, entry path, identity, the cluster, tools and actions, data and keys, the model router with local model servers, and all delivery, observability and licensing components run inside. Below the boundary, the air-gap band lists the only things that ever cross." width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Four things to notice. &lt;strong&gt;There is no provider column.&lt;/strong&gt; The provider builds, signs and prepares bundles and licences, and runs nothing in or near the customer. &lt;strong&gt;The models are local.&lt;/strong&gt; A model router in front of vLLM or Triton on the customer's own GPUs replaces every cloud model call. &lt;strong&gt;The air gap is drawn as a band, not a line.&lt;/strong&gt; The bottom of the diagram is the complete list of what ever crosses, with direction and condition. &lt;strong&gt;The ◆ marker appears nowhere&lt;/strong&gt;, because there is no arrow to put it on.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;connected on-premises variant&lt;/strong&gt; uses the same stack with one difference: bundles are pulled over a single approved outbound HTTPS channel instead of physical media.&lt;/p&gt;

&lt;h3&gt;
  
  
  Request flow
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hop&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Who opens it&lt;/th&gt;
&lt;th&gt;Authentication&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;①&lt;/td&gt;
&lt;td&gt;Global traffic manager → load balancer&lt;/td&gt;
&lt;td&gt;HTTPS/443; internal DNS steers to the active site&lt;/td&gt;
&lt;td&gt;client&lt;/td&gt;
&lt;td&gt;opaque session cookie or token, resolved at the gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;②&lt;/td&gt;
&lt;td&gt;Load balancer → OpenShift Router&lt;/td&gt;
&lt;td&gt;HTTPS/443&lt;/td&gt;
&lt;td&gt;load balancer&lt;/td&gt;
&lt;td&gt;n/a (network hop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;③&lt;/td&gt;
&lt;td&gt;Router → API gateway&lt;/td&gt;
&lt;td&gt;HTTPS/443&lt;/td&gt;
&lt;td&gt;router&lt;/td&gt;
&lt;td&gt;n/a (network hop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;④&lt;/td&gt;
&lt;td&gt;Gateway → identity broker&lt;/td&gt;
&lt;td&gt;HTTPS/443&lt;/td&gt;
&lt;td&gt;gateway&lt;/td&gt;
&lt;td&gt;login and signing keys only; not on the chat path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑤&lt;/td&gt;
&lt;td&gt;Gateway → Chat Gateway&lt;/td&gt;
&lt;td&gt;HTTP/8080 over mTLS&lt;/td&gt;
&lt;td&gt;gateway&lt;/td&gt;
&lt;td&gt;mesh identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑥&lt;/td&gt;
&lt;td&gt;Chat Gateway → Orchestrator&lt;/td&gt;
&lt;td&gt;gRPC over mTLS&lt;/td&gt;
&lt;td&gt;Chat Gateway&lt;/td&gt;
&lt;td&gt;mesh identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑦&lt;/td&gt;
&lt;td&gt;Orchestrator → tools and actions&lt;/td&gt;
&lt;td&gt;gRPC / HTTPS over mTLS&lt;/td&gt;
&lt;td&gt;Orchestrator&lt;/td&gt;
&lt;td&gt;mTLS; the sandbox holds no credentials; per-user tokens from the vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑧&lt;/td&gt;
&lt;td&gt;Orchestrator → retrieval → pgvector&lt;/td&gt;
&lt;td&gt;gRPC; then Postgres/5432&lt;/td&gt;
&lt;td&gt;Orchestrator, then retrieval&lt;/td&gt;
&lt;td&gt;mTLS; database role from Vault; embeddings from a local model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑨&lt;/td&gt;
&lt;td&gt;Orchestrator → model router → local model servers&lt;/td&gt;
&lt;td&gt;gRPC / HTTP over mTLS, inside the cluster&lt;/td&gt;
&lt;td&gt;Orchestrator&lt;/td&gt;
&lt;td&gt;mesh identity; admission control per user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑩&lt;/td&gt;
&lt;td&gt;Orchestrator → connector hub → internal systems&lt;/td&gt;
&lt;td&gt;gRPC; then HTTPS&lt;/td&gt;
&lt;td&gt;Orchestrator, then connector&lt;/td&gt;
&lt;td&gt;mTLS; connector credentials from Vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑪&lt;/td&gt;
&lt;td&gt;Streamed answer → Chat Gateway → user&lt;/td&gt;
&lt;td&gt;SSE over HTTPS&lt;/td&gt;
&lt;td&gt;already open&lt;/td&gt;
&lt;td&gt;same session as ①&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table is almost identical to Pattern 2's. The application does not change between patterns; the ground it stands on does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Common choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Global traffic manager, load balancers, router&lt;/td&gt;
&lt;td&gt;Internal entry path; steers users to the active site&lt;/td&gt;
&lt;td&gt;F5 GTM, NGINX, OpenShift Router&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internal CA&lt;/td&gt;
&lt;td&gt;Certificates for every service, renewed locally&lt;/td&gt;
&lt;td&gt;cert-manager with an internal CA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API gateway, identity broker, directory&lt;/td&gt;
&lt;td&gt;Opaque session resolution; IdP token verified once at login&lt;/td&gt;
&lt;td&gt;Kong, Keycloak, Active Directory or LDAP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cluster: Chat Gateway, Orchestrator, retrieval, connector hub, Redis, mesh&lt;/td&gt;
&lt;td&gt;The application, single-customer, mTLS between every service&lt;/td&gt;
&lt;td&gt;OpenShift, Istio or Linkerd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools and actions&lt;/td&gt;
&lt;td&gt;Sandbox with no egress, action gateway, MCP connectors to internal tools, per-user credential vault, internal webhooks, metering&lt;/td&gt;
&lt;td&gt;gVisor or Firecracker, MCP servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model router, model servers, embedding model&lt;/td&gt;
&lt;td&gt;Several local models behind one interface; request queue and admission control&lt;/td&gt;
&lt;td&gt;vLLM, Triton&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU nodes&lt;/td&gt;
&lt;td&gt;Inference capacity, N+1&lt;/td&gt;
&lt;td&gt;customer-owned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data&lt;/td&gt;
&lt;td&gt;Postgres with pgvector, object storage, offline immutable backups&lt;/td&gt;
&lt;td&gt;CloudNativePG, MinIO, Velero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secrets and keys&lt;/td&gt;
&lt;td&gt;Vault with HSM auto-unseal; local key management&lt;/td&gt;
&lt;td&gt;Vault, HSM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivery&lt;/td&gt;
&lt;td&gt;Scan station, checksum and signature verification with an offline trust root, local registry, GitOps, admission verification&lt;/td&gt;
&lt;td&gt;cosign, Harbor, Argo CD, Kyverno&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability and audit&lt;/td&gt;
&lt;td&gt;All local; SIEM export; self-diagnostics&lt;/td&gt;
&lt;td&gt;Fluent Bit, OpenTelemetry, Loki, Jaeger, VictoriaMetrics, Grafana&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Licensing and time&lt;/td&gt;
&lt;td&gt;Signed licence file verified locally; internal NTP&lt;/td&gt;
&lt;td&gt;custom, NTP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DR data center&lt;/td&gt;
&lt;td&gt;Warm standby: load balancer, minimum-scale cluster, GPU nodes, replicas&lt;/td&gt;
&lt;td&gt;same stack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A facility with no route to the internet
&lt;/h3&gt;

&lt;p&gt;Defence and sovereign environments, where the network is physically isolated and every transfer in or out is a controlled event on approved media. The pattern as drawn.&lt;/p&gt;

&lt;h3&gt;
  
  
  A regulated site that permits one outbound channel
&lt;/h3&gt;

&lt;p&gt;Manufacturing, utilities, some financial institutions. The connected variant: the same stack, with software bundles pulled over one approved outbound HTTPS channel and nothing else leaving. Everything on the diagram stays as drawn except the physical media.&lt;/p&gt;

&lt;h3&gt;
  
  
  An organisation that cannot accept any cloud model provider
&lt;/h3&gt;

&lt;p&gt;Even under their own contract and in their own region, some organisations cannot send prompts to a cloud model provider. Pattern 2 does not help them; this pattern does, at the cost of a local model class and local GPUs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security and privacy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Delivery across an air gap.&lt;/strong&gt; The software pull of Pattern 2 is replaced by a bundle: images, the Helm chart, model weights and an SBOM, signed, written to approved physical media, and carried in through the customer's channel. Inside, it passes a customer-run scan and quarantine station, then checksum and signature verification against an offline trust root that shipped with the first installation. There is no call to a transparency log because there is nothing to call. The trust root is rotated through the same channel, with the old key signing the new one. From the local registry onward, the cluster behaves exactly as in Pattern 2: Argo CD pulls, Kyverno verifies before any pod starts, nothing is hand-applied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identity inside the building.&lt;/strong&gt; The identity broker and the directory both sit inside the facility. The IdP token is verified once at login; the browser then holds an opaque session stored as a hash. CLI tokens and API keys resolve the same way. Certificates come from the internal CA and expiry is monitored, because there is no public CA to fall back on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools and actions with nowhere to go.&lt;/strong&gt; The sandbox has default-deny egress and takes packages only from the local registry mirror; there is no package index to reach, and this constraint belongs in the product documentation. Tool connectors run against internal tool servers only. The action gateway applies policy and approval steps for irreversible actions. Per-user tokens are sealed in a credential vault. Inbound webhooks come only from internal systems, through the same entry path, with signatures verified. Metering writes to a local store with per-department limits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Models on the customer's GPUs.&lt;/strong&gt; A model router fronts several local model servers behind one interface, with a request queue and admission control per user. A local embedding model serves retrieval on the same GPU pool. Nothing calls out. Model updates arrive as weights in the bundle, verified like everything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data, keys and Vault.&lt;/strong&gt; Authorization is one decision point: policy compiled into every query, row-level security beneath. Keys live in a local HSM or software KMS. Backups are offline and immutable, on separate media, because replication copies corruption and ransomware faithfully. Vault unseal uses HSM auto-unseal where possible; with Shamir shares, Vault stays sealed after a power loss until three of five key holders are present, which puts people in the recovery path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reliability
&lt;/h3&gt;

&lt;p&gt;A DR data center runs as a warm standby: a load balancer with a standby VIP, a minimum-scale cluster, GPU nodes for degraded-capacity inference, and replicas of object storage, Postgres, Vault and the registry. Failover is the customer's runbook with human approval; the global traffic manager steers users to the surviving site.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design targets, to be validated in the customer's own failover testing:&lt;/strong&gt; recovery time about one hour; recovery point of seconds to minutes for Postgres and minutes for object storage; reduced GPU capacity until the primary site is restored. A customer with one data center gets local high availability and offline backups, and no site-level DR.&lt;/p&gt;

&lt;p&gt;GPU capacity is the hard ceiling. There is no cloud to burst into. Size for peak, queue beyond it, and build N+1 so one failing node does not stop inference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operations
&lt;/h3&gt;

&lt;p&gt;Everything is local: Fluent Bit, OpenTelemetry, Loki, Jaeger, VictoriaMetrics, a local Grafana, feeding the customer's SIEM together with cluster and infrastructure audit logs. Nothing is collected centrally by the provider, ever. There is no heartbeat because there is no line for it.&lt;/p&gt;

&lt;p&gt;Support has to be designed for this: built-in self-diagnostics with a one-click health report, a redacted support bundle the customer reads before it leaves and sends only if they choose to, and an on-site provider engineer or supervised session only if the customer allows. Remote sessions exist only in the connected variant.&lt;/p&gt;

&lt;p&gt;Patch latency is the operating cost that most needs saying early. Security fixes arrive at the bundle cadence, monthly as standard with emergency bundles for critical CVEs, and each needs a physical transfer, a scan and a verification.&lt;/p&gt;

&lt;p&gt;A signed licence file is verified locally with no network check; expiry leads to a grace period and in-app warnings, never a silent stop. Licence and certificate checks depend on a correct internal NTP source, so clock drift is monitored as a first-class alert.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost
&lt;/h3&gt;

&lt;p&gt;The customer pays for everything: GPUs, servers, storage, a second site, and the people to run them. Nothing is managed. This is the heaviest operating burden of the three patterns by a wide margin, and the only one with capital hardware cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Performance is bounded by local GPU capacity and model class. Only models that can be delivered as weights and served on this hardware are available; frontier hosted models are out of scope by definition. The request queue and admission control make the ceiling visible to users instead of letting requests fail.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design alternatives
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The connected on-premises variant.&lt;/strong&gt; One approved outbound HTTPS channel for bundles. Removes physical media and shortens patch latency, at the cost of one line out of the facility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shamir unseal instead of an HSM.&lt;/strong&gt; Cheaper, but puts people in the recovery path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One data center.&lt;/strong&gt; Removes the second site's cost and gives up site-level DR; local HA and offline backups remain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pattern 2 with a private model endpoint.&lt;/strong&gt; For an organisation that can accept a cloud model provider under its own contract, Pattern 2 is lighter and offers more model choice.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What crosses the air gap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Crossing&lt;/th&gt;
&lt;th&gt;Direction&lt;/th&gt;
&lt;th&gt;What travels&lt;/th&gt;
&lt;th&gt;Who carries it&lt;/th&gt;
&lt;th&gt;Can the customer refuse it?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Offline bundle&lt;/td&gt;
&lt;td&gt;provider → customer, physical media&lt;/td&gt;
&lt;td&gt;signed images, Helm chart, model weights, SBOM&lt;/td&gt;
&lt;td&gt;the customer's approved channel; scanned and verified before the registry&lt;/td&gt;
&lt;td&gt;yes; the running version keeps working&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Licence renewal file&lt;/td&gt;
&lt;td&gt;provider → customer, same channel&lt;/td&gt;
&lt;td&gt;signed file: new expiry and entitlements&lt;/td&gt;
&lt;td&gt;same as above&lt;/td&gt;
&lt;td&gt;yes; expiry means a grace period and warnings, never a silent stop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support bundle (optional)&lt;/td&gt;
&lt;td&gt;customer → provider, manual&lt;/td&gt;
&lt;td&gt;redacted diagnostics the customer read first&lt;/td&gt;
&lt;td&gt;the customer&lt;/td&gt;
&lt;td&gt;yes; never required; the alternative is an engineer on site&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is the whole table. No heartbeat, no software pull, no model call, no sign-in assertion.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The customer runs everything, including GPUs and a second site.&lt;/li&gt;
&lt;li&gt;Model class is fixed by hardware: local open-weight models only.&lt;/li&gt;
&lt;li&gt;Patch latency at the bundle cadence.&lt;/li&gt;
&lt;li&gt;Support works blind: bundles the customer chooses to send, or a visit.&lt;/li&gt;
&lt;li&gt;People in the recovery path unless an HSM is used for unseal.&lt;/li&gt;
&lt;li&gt;No provider commitments on recovery. Every figure is the customer's to validate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to choose this pattern
&lt;/h2&gt;

&lt;p&gt;Choose the isolated site when the rule is &lt;strong&gt;"no prompt leaves this building, and there is no route out"&lt;/strong&gt;, when the organisation can operate Kubernetes, GPUs, databases and a second site, and when a local model class meets the need. If a cloud model provider under their own contract is acceptable, Pattern 2 is lighter. If they want the provider to run it, Pattern 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment outline
&lt;/h2&gt;

&lt;p&gt;Everything arrives as a bundle and is installed by the customer.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;First bundle.&lt;/strong&gt; Images, Helm chart, model weights, SBOM, the offline trust root and the signed licence, on approved media. Scan, verify the checksum and signatures, load into the local registry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foundation.&lt;/strong&gt; The Kubernetes cluster, GPU nodes, Postgres with pgvector, object storage, Vault with HSM auto-unseal, the internal certificate authority and time source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delivery path.&lt;/strong&gt; Argo CD pointed at the local registry, Kyverno with the offline trust root, the scan and quarantine station as a standing procedure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity and entry path.&lt;/strong&gt; The identity broker federated to the internal directory, the global traffic manager, load balancers, router and API gateway with internal certificates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application, tools and models.&lt;/strong&gt; Argo CD applies the signed charts: Chat Gateway, Orchestrator, retrieval, connectors, mesh, the tools-and-actions layer, the model router and model servers with the delivered weights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability, licensing, support.&lt;/strong&gt; Local telemetry into the SIEM, the licence file loaded and verified, self-diagnostics and the support-bundle procedure agreed with the customer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Second site and backups.&lt;/strong&gt; The DR data center with replicas and a minimum-scale cluster, offline immutable backups, then a failover test that replaces the design targets with measured results.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Detailed topology
&lt;/h2&gt;

&lt;p&gt;The full design in twelve bands. The hop numbers match the request flow table above. Open the figure at full size to read the component notes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/dtuzliy93wpiltprbxbk.png" rel="noopener noreferrer"&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%2Fiykvpx37f0bzuqp7xmx4.png" alt="Figure 2. The full isolated-site topology: users, ingress, identity, the OpenShift cluster, local tools and actions, a local model router, local data, secrets, a local-only supply chain, local observability and support, licensing and time, and the air-gap band. A DR data center runs as a warm standby on the right." width="800" height="1619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing between the three patterns
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Pattern 1: shared service&lt;/th&gt;
&lt;th&gt;Pattern 2: control/data split&lt;/th&gt;
&lt;th&gt;Pattern 3: isolated site&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Where the data lives&lt;/td&gt;
&lt;td&gt;provider's account, inside a residency boundary&lt;/td&gt;
&lt;td&gt;customer's cloud account&lt;/td&gt;
&lt;td&gt;customer's building&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Who operates&lt;/td&gt;
&lt;td&gt;provider&lt;/td&gt;
&lt;td&gt;customer (data plane), provider (control plane)&lt;/td&gt;
&lt;td&gt;customer, everything&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;provider's model accounts, pinned to the region&lt;/td&gt;
&lt;td&gt;customer's own cloud model providers&lt;/td&gt;
&lt;td&gt;local models on the customer's GPUs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Software delivery&lt;/td&gt;
&lt;td&gt;provider deploys&lt;/td&gt;
&lt;td&gt;customer pulls signed software&lt;/td&gt;
&lt;td&gt;signed bundle on physical media&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;provider sees its own system&lt;/td&gt;
&lt;td&gt;redacted bundle, or break-glass on the customer's terms&lt;/td&gt;
&lt;td&gt;redacted bundle or on-site visit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operating burden on the customer&lt;/td&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;heavy&lt;/td&gt;
&lt;td&gt;heaviest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What crosses the boundary&lt;/td&gt;
&lt;td&gt;every user's traffic, inside the boundary&lt;/td&gt;
&lt;td&gt;software pull, opt-in heartbeat, support; model call to the customer's own provider&lt;/td&gt;
&lt;td&gt;two signed files in, one optional file out&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three patterns, one application, the same three questions. If you can answer them for your own system, with every crossing drawn and every figure labelled for what it is, you can answer the questions a security review will ask.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This is part 3 of a three-part series. The other parts are also linked in the series box at the top of this article.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-1-the-shared-service-saas-4k6o"&gt;Pattern 1, the shared service (SaaS)&lt;/a&gt;: the provider runs everything inside a residency boundary.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-2-the-controldata-split-customer-cloud-4mf9"&gt;Pattern 2, the control/data split (customer cloud)&lt;/a&gt;: the customer runs the whole data plane in their own cloud account.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>ai</category>
      <category>kubernetes</category>
      <category>security</category>
    </item>
    <item>
      <title>How to deploy an AI assistant: Pattern 1, the shared service (SaaS)</title>
      <dc:creator>Rajesh Yadav</dc:creator>
      <pubDate>Sat, 17 Oct 2026 14:03:52 +0000</pubDate>
      <link>https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-1-the-shared-service-saas-4k6o</link>
      <guid>https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-1-the-shared-service-saas-4k6o</guid>
      <description>&lt;p&gt;&lt;em&gt;A reference architecture for running one AI assistant platform for many organisations, inside a data-residency boundary&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;This document describes a deployment pattern for an AI assistant platform: a system that answers questions over an organisation's documents, calls its internal tools, and takes actions on its behalf. It is written for architects and platform engineers who have to decide &lt;strong&gt;where such a system runs&lt;/strong&gt; and have to defend that decision in a security review.&lt;/p&gt;

&lt;p&gt;It is the first of three documents. Each covers one deployment pattern with the same structure: a one-picture architecture, the request flow, the components, use cases, design considerations, what crosses the boundary, and when to choose it. The design is independent of any product. The technologies named (Kong, Keycloak, Argo CD, Vault, pgvector, vLLM) are common choices and can be replaced without changing the design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terms used throughout.&lt;/strong&gt; The &lt;em&gt;provider&lt;/em&gt; is whoever builds and operates the platform: a vendor, or an internal platform team. The &lt;em&gt;customer&lt;/em&gt; is the organisation whose users and data the platform serves: an external customer, or a business unit of your own company. A &lt;em&gt;tenant&lt;/em&gt; is one customer on a shared platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites.&lt;/strong&gt; A cloud account with two regions inside the required residency geography, a Kubernetes service, managed Postgres and object storage, a key management service, and access to at least one model provider with a region inside the geography. A team that already runs Kubernetes in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Out of scope.&lt;/strong&gt; Model quality, prompt design and the assistant's features. This series covers only where and how the platform runs.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three patterns at a glance
&lt;/h2&gt;

&lt;p&gt;Three questions decide the pattern. Ask them in this order.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Where does the data live?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Who operates the system?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What crosses the boundary between the provider and the customer?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Data lives in&lt;/th&gt;
&lt;th&gt;Operated by&lt;/th&gt;
&lt;th&gt;Crosses the boundary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1. Shared service (this document)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;the provider's account, inside a residency boundary&lt;/td&gt;
&lt;td&gt;the provider&lt;/td&gt;
&lt;td&gt;every user's traffic, inside the boundary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Control/data split&lt;/td&gt;
&lt;td&gt;the customer's cloud account&lt;/td&gt;
&lt;td&gt;the customer runs the data plane; the provider runs a control plane&lt;/td&gt;
&lt;td&gt;signed software in, optional health metadata out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Isolated site&lt;/td&gt;
&lt;td&gt;the customer's building&lt;/td&gt;
&lt;td&gt;the customer, everything&lt;/td&gt;
&lt;td&gt;two signed files in, one optional file out&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most organisations are served well by Pattern 1. Patterns 2 and 3 exist for the ones whose rules make it impossible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&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%2Fxwzzmkndtv2bklctytu6.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%2Fxwzzmkndtv2bklctytu6.png" alt="Figure 1. The shared-service pattern. Users and each tenant's identity provider sit outside the boundary. Inside: a global edge, an API gateway, an identity broker, a shared compute cell with a tools-and-actions layer, data with a policy decision point, a model router, controlled egress, and a warm-standby region." width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What makes it shared.&lt;/strong&gt; Ten to fifteen tenants run in one Kubernetes cell, share one database cluster, and draw on the same model capacity. &lt;strong&gt;What makes it safe to share.&lt;/strong&gt; Tenant identity is taken only from a credential the platform resolved itself, and every layer below re-checks it. &lt;strong&gt;Who runs it.&lt;/strong&gt; The provider operates everything except the tenant's own identity provider and the tenant's internal systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Request flow
&lt;/h3&gt;

&lt;p&gt;The numbered hops follow one chat message through the detailed topology at the end of this document.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hop&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Who opens it&lt;/th&gt;
&lt;th&gt;Authentication&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;①&lt;/td&gt;
&lt;td&gt;Client → CDN edge&lt;/td&gt;
&lt;td&gt;HTTPS/443&lt;/td&gt;
&lt;td&gt;client&lt;/td&gt;
&lt;td&gt;opaque session cookie, personal token or API key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;②&lt;/td&gt;
&lt;td&gt;Edge → anycast entry point&lt;/td&gt;
&lt;td&gt;HTTPS/443&lt;/td&gt;
&lt;td&gt;edge&lt;/td&gt;
&lt;td&gt;secret origin header, checked at the gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;③&lt;/td&gt;
&lt;td&gt;Anycast entry → network load balancer&lt;/td&gt;
&lt;td&gt;TCP/443&lt;/td&gt;
&lt;td&gt;anycast&lt;/td&gt;
&lt;td&gt;none; TLS pass-through&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;④&lt;/td&gt;
&lt;td&gt;Load balancer → API gateway&lt;/td&gt;
&lt;td&gt;TCP/443&lt;/td&gt;
&lt;td&gt;load balancer&lt;/td&gt;
&lt;td&gt;the caller's credential is resolved here&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑤&lt;/td&gt;
&lt;td&gt;Gateway → identity broker&lt;/td&gt;
&lt;td&gt;HTTPS/443&lt;/td&gt;
&lt;td&gt;gateway&lt;/td&gt;
&lt;td&gt;mesh identity; login only, not on the chat path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑥&lt;/td&gt;
&lt;td&gt;Gateway → Chat Gateway&lt;/td&gt;
&lt;td&gt;HTTP/8080 over mTLS&lt;/td&gt;
&lt;td&gt;gateway&lt;/td&gt;
&lt;td&gt;mesh identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑦&lt;/td&gt;
&lt;td&gt;Chat Gateway → Orchestrator&lt;/td&gt;
&lt;td&gt;gRPC over mTLS&lt;/td&gt;
&lt;td&gt;Chat Gateway&lt;/td&gt;
&lt;td&gt;mesh identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑧&lt;/td&gt;
&lt;td&gt;Orchestrator → tools and actions&lt;/td&gt;
&lt;td&gt;gRPC / HTTPS over mTLS&lt;/td&gt;
&lt;td&gt;Orchestrator&lt;/td&gt;
&lt;td&gt;mTLS; the sandbox holds no credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑨&lt;/td&gt;
&lt;td&gt;Orchestrator → data&lt;/td&gt;
&lt;td&gt;Postgres, Redis, S3&lt;/td&gt;
&lt;td&gt;Orchestrator&lt;/td&gt;
&lt;td&gt;cloud IAM role per tenant; per-tenant Redis ACL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑩&lt;/td&gt;
&lt;td&gt;Orchestrator → model router → model providers&lt;/td&gt;
&lt;td&gt;HTTPS/443, private endpoints&lt;/td&gt;
&lt;td&gt;Orchestrator&lt;/td&gt;
&lt;td&gt;cloud IAM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⑪&lt;/td&gt;
&lt;td&gt;Egress gateway → NAT → customer system&lt;/td&gt;
&lt;td&gt;HTTPS/443 from static addresses&lt;/td&gt;
&lt;td&gt;Orchestrator, via egress&lt;/td&gt;
&lt;td&gt;per-tenant credential from Vault&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The answer streams back over the connection the client opened. If it drops, the client resumes from the last sequence number it received, for as long as the turn buffer holds it (about five minutes).&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Common choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CDN edge&lt;/td&gt;
&lt;td&gt;TLS termination, web application firewall, DDoS protection, static cache; adds the secret origin header&lt;/td&gt;
&lt;td&gt;CloudFront, Cloudflare&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anycast entry point&lt;/td&gt;
&lt;td&gt;One stable address per residency boundary; traffic dial for failover&lt;/td&gt;
&lt;td&gt;AWS Global Accelerator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API gateway&lt;/td&gt;
&lt;td&gt;Resolves the caller, strips client-sent tenant headers, injects its own, rate limits&lt;/td&gt;
&lt;td&gt;Kong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity broker&lt;/td&gt;
&lt;td&gt;One realm per tenant, federated to the tenant's identity provider&lt;/td&gt;
&lt;td&gt;Keycloak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat Gateway&lt;/td&gt;
&lt;td&gt;Server-sent events streaming, heartbeat, resume from the turn buffer&lt;/td&gt;
&lt;td&gt;custom service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Orchestrator&lt;/td&gt;
&lt;td&gt;Durable step runtime: every inference and tool call is a resumable step&lt;/td&gt;
&lt;td&gt;Temporal, custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools and actions&lt;/td&gt;
&lt;td&gt;Code sandbox, action gateway, tool connectors, per-user credential vault, inbound webhooks, metering&lt;/td&gt;
&lt;td&gt;gVisor or Firecracker, MCP servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data&lt;/td&gt;
&lt;td&gt;Postgres with pgvector, object storage per tenant prefix, Redis turn buffer, one KMS key per tenant&lt;/td&gt;
&lt;td&gt;Aurora, S3, ElastiCache, KMS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model router&lt;/td&gt;
&lt;td&gt;One interface over several model providers, each pinned to a region&lt;/td&gt;
&lt;td&gt;custom, LiteLLM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Egress gateway and NAT&lt;/td&gt;
&lt;td&gt;Allowlisted outbound calls from static addresses in both regions&lt;/td&gt;
&lt;td&gt;Envoy, NAT gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delivery&lt;/td&gt;
&lt;td&gt;GitOps for everything, signed images verified at admission, promotion gate&lt;/td&gt;
&lt;td&gt;Argo CD, cosign, Kyverno&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability and audit&lt;/td&gt;
&lt;td&gt;Independent telemetry per region, synthetic canaries, one immutable audit trail&lt;/td&gt;
&lt;td&gt;OpenTelemetry, Grafana, S3 Object Lock&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A vendor serving many organisations from one platform
&lt;/h3&gt;

&lt;p&gt;The classic SaaS case. The provider wants one codebase, one deployment, and one on-call rotation. Customers want a product that works on day one and accept that their content is stored in the provider's account, inside an agreed region.&lt;/p&gt;

&lt;h3&gt;
  
  
  An internal platform team serving many business units
&lt;/h3&gt;

&lt;p&gt;The same design works inside one company. Business units are tenants, the platform team is the provider, and the residency boundary is the company's own cloud region. The isolation layers matter just as much: finance should not see legal's documents because they share a cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  A regulated customer who needs residency but not isolation
&lt;/h3&gt;

&lt;p&gt;A customer who must keep data in a specific country can be served by Pattern 1 as long as the provider runs a full regional pair inside that country. Residency is a property of where the boundary is drawn, not of who operates the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security and privacy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Only one way in.&lt;/strong&gt; The edge adds a rotating secret header that the gateway requires. An attacker who finds the origin's address gains nothing, because the origin refuses anything that did not come through the edge and its firewall. Admins get a separate edge path with stricter rules and an optional IP allowlist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gateway resolves the caller; it does not trust a bearer token.&lt;/strong&gt; Browser sessions are opaque secrets whose hash is stored server-side. CLI tokens and API keys are resolved the same way. The identity provider's JWT is verified once, at login, and never used as a request credential again. Nothing at rest is replayable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tenant identity comes only from the platform.&lt;/strong&gt; The gateway strips any tenant header the client sent and injects its own, derived from the resolved principal. Every layer below re-checks it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isolation in eight layers.&lt;/strong&gt; Tenants share a cell, so isolation is layered, and a failure in one layer is caught by the next.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Per-tenant control&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Identity&lt;/td&gt;
&lt;td&gt;Own realm; tenant claim issued by the broker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway&lt;/td&gt;
&lt;td&gt;Own consumer, rate limit and quota&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cluster&lt;/td&gt;
&lt;td&gt;Namespace with default-deny NetworkPolicy, scoped RBAC, ResourceQuota&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mesh&lt;/td&gt;
&lt;td&gt;Authorization policy that re-checks the tenant claim on every hop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud IAM&lt;/td&gt;
&lt;td&gt;Own IAM role; no long-lived keys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data&lt;/td&gt;
&lt;td&gt;Policy compiled into every query, row-level security beneath it, own object prefix, own Redis ACL, own KMS key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Egress&lt;/td&gt;
&lt;td&gt;Own destination allowlist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model&lt;/td&gt;
&lt;td&gt;Own token budget and context limit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Tenancy has two levels: an organisation and the workspaces inside it. Workspaces share the tenant's namespace and are separated by policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authorization is decided once.&lt;/strong&gt; One policy decision point evaluates tenant and user policy and compiles it into every query. There is no "load then filter" in application code. Row-level security sits beneath it as defence in depth, not as the policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools and actions are gated.&lt;/strong&gt; The sandbox holds no platform credentials and has default-deny egress with an allowlist of package registries. Email, messaging and writes go through an action gateway with per-tenant policy, an approval step for irreversible actions, and an audit record for each action. Tool connectors run against a per-tenant allowlist. Per-user tokens are sealed in a credential vault the model and the sandbox never see. Inbound webhooks enter through the edge with signature verification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Each model provider is its own boundary.&lt;/strong&gt; The router pins each provider to a region inside the residency boundary, uses private endpoints, and keeps invocation logging off. Residency and logging are recorded per provider, never "per platform".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keys and exit.&lt;/strong&gt; Each tenant has one multi-region KMS key, with an optional bring-your-own-key grant. At exit the key is disabled immediately and deleted after the KMS waiting period, which makes the tenant's data unreadable. Chat content is never written to logs; gateways, collectors and log shippers strip bodies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reliability
&lt;/h3&gt;

&lt;p&gt;A second region runs as a warm standby at minimum scale: ingress, identity, the cell with its tools layer, data replicas, its own model capacity, its own NAT addresses and its own telemetry. Failover is deliberately not automatic. A person approves, then an orchestrator promotes the database, scales the cell and gateway, and moves the anycast traffic dial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design targets, to be validated in failover testing:&lt;/strong&gt; recovery time about 15 minutes; recovery point of seconds for the database and within 15 minutes for object storage; the Redis turn buffer is lost, so chats in progress restart.&lt;/p&gt;

&lt;p&gt;The identity broker is the single login dependency for every tenant. If it is down, nobody signs in. Its state lives in a global database so it survives a regional failover, but not its own outage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operations
&lt;/h3&gt;

&lt;p&gt;Everything is delivered by GitOps, routes included. Nothing is hand-applied, self-heal is on, and promotion to production goes through a gate. Images are signed and the signature is verified at admission.&lt;/p&gt;

&lt;p&gt;Each region has an independent telemetry stack. Synthetic canaries probe from outside the platform through the real edge, so operators see what users see. One audit trail collects cloud API calls, cluster and gateway audit, every agent action with its tenant and user, and every break-glass session, normalised to one schema and written to immutable storage. Every line carries a credential id, never the secret.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost
&lt;/h3&gt;

&lt;p&gt;The shared cell is the main saving: one cluster, one database cluster and one model quota serve many tenants. The main costs are the warm standby, which runs all the time, and the edge plus anycast plus gateway plus mesh stack, which is more components than any one alone. Each residency geography needs its own full regional pair, so the cost scales with the number of geographies, not the number of tenants.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;The chat tier scales on active streaming connections, not CPU, because idle connections use almost none. Model capacity is shared per account per region and controlled by per-tenant token budgets. Tool output is capped so one call cannot consume the context budget.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design alternatives
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DNS-only failover instead of an anycast entry.&lt;/strong&gt; Cheaper, but depends on resolver caches honouring TTLs. The traffic dial switches new connections in seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An application load balancer instead of a layer-4 load balancer.&lt;/strong&gt; Would terminate TLS twice and duplicate the routing the gateway already does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A database per tenant.&lt;/strong&gt; Removes the shared cluster key and blast radius at the cost of many more clusters. Right for a premium or regulated tier, not the default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trusting the identity provider's JWT on every request.&lt;/strong&gt; Simpler, but a long-lived bearer token at rest is replayable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A managed sandbox service.&lt;/strong&gt; Less to operate, but it is a third party that sees content, and it must appear in the boundary table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic failover.&lt;/strong&gt; Faster, until it fires on a false alarm.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What crosses the boundary
&lt;/h2&gt;

&lt;p&gt;Fill this table in for your own design before a security review asks for it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Crossing&lt;/th&gt;
&lt;th&gt;Direction&lt;/th&gt;
&lt;th&gt;What travels&lt;/th&gt;
&lt;th&gt;Can the customer switch it off?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User traffic → edge&lt;/td&gt;
&lt;td&gt;customer → provider&lt;/td&gt;
&lt;td&gt;requests and streamed answers&lt;/td&gt;
&lt;td&gt;no, it is the product; the customer controls accounts and the admin allowlist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity broker ↔ tenant IdP&lt;/td&gt;
&lt;td&gt;both, sign-in only&lt;/td&gt;
&lt;td&gt;assertions and claims, no business data&lt;/td&gt;
&lt;td&gt;yes; disabling federation stops sign-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model router → model providers&lt;/td&gt;
&lt;td&gt;provider → model providers&lt;/td&gt;
&lt;td&gt;prompts with retrieved content&lt;/td&gt;
&lt;td&gt;no; per-provider residency and logging terms are recorded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sandbox and tool servers&lt;/td&gt;
&lt;td&gt;provider → sandbox and allowlisted tools&lt;/td&gt;
&lt;td&gt;code, files, tool inputs&lt;/td&gt;
&lt;td&gt;yes, per tool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Action gateway → channels&lt;/td&gt;
&lt;td&gt;provider → email, messaging, systems&lt;/td&gt;
&lt;td&gt;the agent's actions&lt;/td&gt;
&lt;td&gt;yes, per action type and tenant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inbound webhooks&lt;/td&gt;
&lt;td&gt;third parties → edge → gateway&lt;/td&gt;
&lt;td&gt;signed callbacks&lt;/td&gt;
&lt;td&gt;yes, by not enabling the channel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Egress → customer systems&lt;/td&gt;
&lt;td&gt;provider → customer, from static addresses&lt;/td&gt;
&lt;td&gt;connector calls and results&lt;/td&gt;
&lt;td&gt;yes; remove the firewall rule or disable the connector&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-tenant SIEM export&lt;/td&gt;
&lt;td&gt;provider → customer&lt;/td&gt;
&lt;td&gt;that tenant's audit events&lt;/td&gt;
&lt;td&gt;yes, opt-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bring-your-own-key grant&lt;/td&gt;
&lt;td&gt;customer → provider&lt;/td&gt;
&lt;td&gt;permission to use the customer's key&lt;/td&gt;
&lt;td&gt;yes; revoking makes that tenant's data unreadable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tenants share a cluster and a database cluster key. One cell's blast radius spans its tenants.&lt;/li&gt;
&lt;li&gt;Model quota is shared per account per region, controlled by per-tenant budgets.&lt;/li&gt;
&lt;li&gt;The identity broker is the single login dependency.&lt;/li&gt;
&lt;li&gt;Failover is human-approved and takes about 15 minutes as a design target. Chats in progress restart.&lt;/li&gt;
&lt;li&gt;Each residency geography needs its own regional pair.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to choose this pattern
&lt;/h2&gt;

&lt;p&gt;Choose the shared service when the customer wants the provider to run everything, accepts content stored in the provider's account inside an agreed residency boundary, and does not need an air gap. Put the effort into the eight isolation layers and the audit trail.&lt;/p&gt;

&lt;p&gt;Choose Pattern 2 if the customer's documents, index and keys must stay in their own account under a key they can revoke. Choose Pattern 3 if nothing may leave their building, not even a prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment outline
&lt;/h2&gt;

&lt;p&gt;Build from the inside out, so that each layer is verified before the next depends on it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Foundation.&lt;/strong&gt; Two regions, VPCs, the Kubernetes cell in each, the global database with its replica, object storage with cross-region replication, one KMS key per tenant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity and gateway.&lt;/strong&gt; The identity broker with one realm per tenant, federated to each tenant's identity provider. The API gateway with opaque session resolution, per-tenant consumers and the tenant-header rule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge.&lt;/strong&gt; The CDN distribution with WAF and the secret origin header, the anycast entry point with the Region B dial at zero, the separate admin distribution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application.&lt;/strong&gt; Chat Gateway, Orchestrator, retrieval and connector services, the service mesh with mTLS and the tenant re-check policy, the admission controller that generates namespaces, quotas and network policies per tenant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools and actions.&lt;/strong&gt; The sandbox with default-deny egress, the action gateway, tool connectors, the per-user credential vault, webhook intake, metering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model router and egress.&lt;/strong&gt; Providers pinned to regions, private endpoints, invocation logging off; the egress gateway and NAT with static addresses in both regions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delivery and observability.&lt;/strong&gt; GitOps for every component, image signing and admission verification, the promotion gate; telemetry per region, synthetic canaries, the audit pipeline into immutable storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failover.&lt;/strong&gt; The DR orchestrator and runbook, then a full failover test that measures the recovery figures and replaces the design targets with results.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Detailed topology
&lt;/h2&gt;

&lt;p&gt;The full design in thirteen bands, in the order a request travels. The hop numbers match the request flow table above. Open the figure at full size to read the component notes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/gbw7f9rxntp21g43h54p.png" rel="noopener noreferrer"&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%2Fyujgyd4bjuxle4xjnjp4.png" alt="Figure 2. The full shared-service topology: clients and inbound callers, global edge, ingress, identity, compute cell, tools and actions, data, model router, outbound to customer systems, warm-standby region, delivery, observability, and audit." width="800" height="2423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This is part 1 of a three-part series. The other parts are also linked in the series box at the top of this article.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-2-the-controldata-split-customer-cloud-4mf9"&gt;Pattern 2, the control/data split (customer cloud)&lt;/a&gt;: the customer runs the whole data plane in their own cloud account.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/rajesh_yadav_devops/how-to-deploy-an-ai-assistant-pattern-3-the-isolated-site-on-premises-and-air-gapped-259b"&gt;Pattern 3, the isolated site (on-premises and air-gapped)&lt;/a&gt;: everything runs in the customer's building, with models on local GPUs.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>ai</category>
      <category>kubernetes</category>
      <category>security</category>
    </item>
  </channel>
</rss>
