> ## Documentation Index
> Fetch the complete documentation index at: https://docs.superblocks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Reference architectures

> Recommended AWS layout for Superblocks data planes, plus the less common layouts that justify more planes or tags

Examples use AWS because it is the most common target and the only one that supports [Superblocks Database](/enterprise/hybrid-architecture/plan/superblocks-database), but the same shapes apply on GCP and Azure, and all of them assume you have read [Plan your data planes](/enterprise/hybrid-architecture/plan/index).

## Recommended: two AWS accounts, two data planes

Most organizations already separate pre-production and production into different AWS accounts. Put one data plane in each, and give each one exactly one data tag.

```mermaid theme={null}
flowchart LR
  EndUser["End users<br/>deployed apps"]
  Builder["Builders<br/>Edit and Preview"]

  subgraph prodAccount [AWS account: production VPC]
    ProdPlane["Production data plane<br/>profile:production"]
    ProdDb[("Production database")]
  end

  subgraph devAccount [AWS account: pre-production VPC]
    DevPlane["Development data plane<br/>profile:dev"]
    StagingDb[("Staging database")]
  end

  EndUser -->|"production tag"| ProdPlane --> ProdDb
  Builder -->|"dev tag"| DevPlane --> StagingDb
```

Why this is the default recommendation:

* **Tag routing and the account boundary work together.** Superblocks sends a request to the data plane that serves its data tag, so Edit and Preview traffic on `dev` only ever runs on the development data plane. Because that data plane lives in the pre-production account, anything reachable only from inside the production VPC, such as the production database above, is out of reach from Edit even if an integration is misconfigured. IAM, networking, and billing are already separated, so you write no extra policy to get this.
* **Two data tags are the minimum that gives you separation**, and few enough that builders rarely pick the wrong one. The built-in **Development** (`dev`) and **Production** (`production`) tags already exist for this.
* **Clark stays on the development side.** Clark only runs in Edit, so with Edit on the `dev` tag it never routes through the production account or VPC. See [Clark and data access](/building-with-clark/data-access).

This boundary covers data that only the production network can reach. A third-party configuration linked to both tags, such as a Salesforce or Jira tenant with no sandbox, is the same live system from either data plane; see [Sharing a third-party configuration between dev and production](/enterprise/hybrid-architecture/plan/index#sharing-a-third-party-configuration-between-dev-and-production) for how to scope what Edit can do to it.

To build it, deploy each data plane with [ECS Fargate](/enterprise/hybrid-architecture/deployment/aws_ecs_fargate) or [Kubernetes](/enterprise/hybrid-architecture/deployment/kubernetes) and set its agent tags as described in [Set agent tags](/enterprise/hybrid-architecture/deployment/multiple_environments).

## Less common layouts

Each layout below adds a data plane, a data tag, or both. See [Data planes and Superblocks Database](/enterprise/hybrid-architecture/plan/superblocks-database) if you plan to enable databases.

### Single AWS account

Some organizations run everything in one AWS account. Keep the two data planes and two data tags, and put each data plane in its own VPC, or at least its own subnets and security groups.

```mermaid theme={null}
flowchart LR
  EndUser["End users<br/>deployed apps"]
  Builder["Builders<br/>Edit and Preview"]

  subgraph account [AWS account]
    subgraph prodVpc [VPC: production]
      ProdPlane["Production data plane<br/>profile:production"]
      ProdDb[("Production database")]
    end
    subgraph devVpc [VPC: pre-production]
      DevPlane["Development data plane<br/>profile:dev"]
      StagingDb[("Staging database")]
    end
  end

  EndUser -->|"production tag"| ProdPlane --> ProdDb
  Builder -->|"dev tag"| DevPlane --> StagingDb
```

Implications:

* Separation now depends on security groups and IAM policies you write, not on an account boundary.
* Both data planes share IAM role and resource namespaces, so each needs a distinct agent name.

### Production with a VPC-only tag and a non-VPC tag

Some organizations have two kinds of production apps: a few that need private data inside the VPC, and many that only use SaaS tools or public APIs. Rather than give every production request a path into the private network, they run two production data planes with two production data tags. The second data plane runs in its own VPC with no peering, transit gateway attachment, or route to the VPC that holds private data; it still sits in private subnets and reaches SaaS and the control plane through NAT egress, like any other data plane.

```mermaid theme={null}
flowchart LR
  AppA["Apps that need private data<br/>production-vpc tag"]
  AppB["Apps that only use SaaS<br/>production tag"]

  subgraph prodAccount [AWS account: production]
    subgraph privateVpc [VPC with private data]
      VpcPlane["Production data plane<br/>profile:production-vpc"]
      ProdDb[("Production database")]
    end
    subgraph saasVpc [Separate VPC, not peered]
      SaasPlane["Production data plane<br/>profile:production"]
    end
  end

  AppA --> VpcPlane --> ProdDb
  AppB --> SaasPlane
```

Implications:

* Production has two data tags, so every app must choose the right one for its Production environment.
* The private data plane's access footprint is smaller: only apps tagged `production-vpc` can reach it.
* The separation is only as good as the network boundary. Two VPCs with no peering or shared routes give it to you by default; if both data planes must share one VPC, security groups and network ACLs have to deny the SaaS-only data plane every path to the private data, and you own keeping that rule set correct.

The same shape applies when a single data source lives in a locked-down network segment: run a dedicated data plane inside that segment with its own tag, and only the apps that need that source use it.

#### With Superblocks Database

[Superblocks Database](/enterprise/hybrid-architecture/plan/superblocks-database) creates one database per app per data tag, so an app whose Production environment allows both `production-vpc` and `production` would get two production databases, one in each data plane's pool. Superblocks recommends a third production tag for the apps that serve both an internal and a public audience. The SaaS-only data plane serves it alongside `production`, with agent tags `profile:production,profile:production-shared`:

| Data tag            | Served by                               | Apps                                         |
| ------------------- | --------------------------------------- | -------------------------------------------- |
| `production-vpc`    | Data plane in the VPC with private data | Internal apps that need private data         |
| `production`        | SaaS-only data plane                    | Apps that only use SaaS tools or public APIs |
| `production-shared` | SaaS-only data plane                    | Apps used both internally and publicly       |

Each app then has exactly one production tag and one production database. The app's developer picks that tag before publishing for the first time, because the first publish creates the production database under that tag and [data tag keys are permanent once databases exist](/enterprise/hybrid-architecture/plan/superblocks-database#one-database-enabled-data-plane-per-data-tag).

### Multi-region

When users or data live in more than one region, run a data plane in each region and give each region its own data tag. Apps allow several tags in Production, and end users switch regions by switching tags.

```mermaid theme={null}
flowchart TB
  subgraph useast [AWS us-east-1]
    EastPlane["Data plane<br/>profile:us-east"]
    EastDb[("Regional database")]
  end
  subgraph euwest [AWS eu-west-1]
    WestPlane["Data plane<br/>profile:eu-west"]
    WestDb[("Regional database")]
  end

  Users["End users"]
  Users -->|"us-east tag"| EastPlane --> EastDb
  Users -->|"eu-west tag"| WestPlane --> WestDb
```

Implications:

* You still need a pre-production data plane and tag; regional tags are usually production-only. That makes at least three data planes.
* Every integration with regional instances needs a configuration per region.

### IAM-based access patterns

When the data plane runs in AWS, its IAM role is the identity that AWS integrations authenticate with; see [AWS IAM](/integrations/auth/aws-iam). If different groups of apps need different AWS permissions, you can run separate data planes, each with its own IAM role and data tag, instead of granting one data plane the union of every permission.

Implications:

* Every app must run with the tag whose data plane holds the permissions it needs; a mismatch fails at execution time, not at build time.
