The short version
- Nothing connects into your network. Your data plane opens every connection; the control plane never initiates one and is not in any cluster’s security group ingress.
- The control plane holds none of the feature’s credentials. It cannot assume either IAM role, has no database credentials, and has no route to a cluster. It retains lifecycle state and connection metadata, never application data or credentials.
- IAM policies you review and own decide which resources can change. The lifecycle worker role can create, modify, or delete only resources that carry the tags Superblocks stamps at creation, inside the one VPC you declared, and you can revoke it at any time.
- No application password ever exists. Applications connect with 15-minute RDS IAM tokens, each limited to one PostgreSQL role on one cluster.
- Clusters cannot be public or unencrypted. IAM conditions require
publicly_accessible = false, storage encryption, and an RDS-managed master password on every cluster, so a modified module cannot opt out.
What runs where
In a Hybrid deployment the control plane is Superblocks Cloud, outside your account. In Cloud-Prem it runs inside your AWS account under its own identity, operated by Superblocks. The trust boundary is the same in both: the control plane is not a principal in either role’s trust policy, is not in any cluster’s security group ingress, and never opens a connection to the data plane.- Hybrid
- Cloud-Prem
source_security_group_ids and allowed_cidr_blocks, normally your data plane’s security group and nothing else. See Physical database options.
Each application gets its own PostgreSQL database and its own PostgreSQL role, created with rds_iam and no password, so the only way to log in as that role is an RDS IAM token. The connector role’s policy allows rds-db:connect only for application runtime roles under the data tags you declared, and the per-connection session policy narrows that to the one role and one cluster being served. One application therefore cannot authenticate as another application or as the master user, even though every application on the data plane shares the same connector role. The full sequence is under Connecting.
What you are asked to grant
Setup runs one Terraform module,app-db-prereqs, once per region in each account. It creates the four items below and nothing else; the first Aurora cluster is created when an organization admin clicks Provision. From then on the worker acts without a human gate: it creates a database whenever a builder needs one, and another cluster whenever remaining pool capacity falls to the thresholds in your data plane configuration. The number of clusters is bounded by those thresholds and your AWS quotas, not by IAM.
- No cross-account trust. No trust policy names a Superblocks account, so no Superblocks system outside your account can assume either role. If Superblocks operates your data plane for you (Cloud-Prem with managed data planes), its operators act through the data plane’s identity, and every role assumption is in your CloudTrail.
- No IAM administration. The worker’s only IAM permissions are
iam:PassRolefor the monitoring role andiam:CreateServiceLinkedRolefor the RDS service-linked role. It cannot create roles, attach policies, or change its own permissions. - No tagging escape hatch. The tagging permissions are conditioned too, so the worker cannot bring an arbitrary resource of yours into scope by tagging it, and it is explicitly denied removing the scoping tags from anything. The exact conditions are in the Raw IAM policy JSON.
- No reach outside the VPC. Every mutating permission is conditioned on the VPC you declared.
- No long-lived credentials. The worker role is assumed through ECS or IRSA. It can read the RDS-managed master secret for clusters it created, which RDS creates and rotates, but cannot create, write, or export secrets. The agent key it uses toward the control plane grants nothing in AWS.
How work is dispatched
Every change starts as a task the control plane queues and ends with your data plane deciding whether to carry it out. Registering the database capability rides on the same/api/v1/agents/register call every data plane already makes; the rest use the database-lifecycle routes.
The data plane also polls the claim route every 30 seconds, so the server-sent events stream only shortens the wait: if it errors or is unavailable, polling continues. Neither the hint nor the stream carries a task; the task is always fetched through the claim route. A proxy that buffers the stream adds latency, nothing more.
What bounds a task
Enforced in your account, independent of Superblocks:- Direction. The data plane pulls work over connections it opens. The control plane cannot reach the data plane, call AWS, or connect to a database.
- IAM on the AWS path. Creates, modifies, and deletes are confined to tagged resources in the declared VPC, and public endpoints and unencrypted storage are denied by condition. A task that asks for anything else fails with
AccessDenied. - Identity on the database path. Queries and migrations run as the application’s own PostgreSQL role, over the connector role. Create and retire run as the master user, bounded not by IAM but by the allowlisted module, which executes the DDL for the named database and its roles and nothing else.
- Allowlists on the data plane. The worker builds the OpenTofu configuration only from module sources on an allowlist in its own configuration, runs
tofu plan, and rejects any plan that touches a resource type outside its allowlist. - Network. Clusters accept connections only from the security groups and CIDR ranges you configured.
- Tasks are routed only to a data plane registered for the exact data tag they belong to, and wildcard data tags are rejected at registration.
- Task payloads carry intent and the application’s schema files but never credentials, and outcome reports that contain credential material are rejected.
Residual risk
If the control plane were compromised, an attacker could queue tasks but not execute them, and nothing the data plane executes can escape the account-side bounds above. Within those bounds, the worst case is:- Destructive changes to clusters the worker already manages, such as deleting or resizing them. Neither the allowlists nor IAM independently block a destructive plan against an in-footprint cluster;
deletion_protection(defaulttrue), automated backups, and the final snapshot on deletion are the controls that apply. - Loss or corruption of application data across the data plane, either through attacker-chosen migration SQL running as each application’s own role in its own database, or through queued retires dropping each application’s database. Backups are the recovery path.
- Unexpected spend from queued cluster creations, up to your pool thresholds and AWS quotas.
How to verify
Before setup
- Read the Raw IAM policy JSON for both roles. The Terraform module attaches exactly these policies, and that section is written to be handed to an IAM approver as is.
- Read the module source.
app-db-prereqsis published in thesuperblocksteam/superblocks/awsregistry module, and itsterraform planoutput lists every resource it will create before you apply it. - Read the outbound requests the data plane makes, and confirm your egress path allows them. No inbound rule is required.
- Confirm the inputs you will pass: the VPC, the private subnets, the security groups allowed to reach port 5432, and the data tags. Each becomes a condition in the policies above.
After setup
Everything the feature manages is discoverable from your account, without involving Superblocks. IAM is global, but the tagging and RDS commands below are regional; run them in every region where you deployed a data plane.AssumeRole on the connector role, and every master-user session starts with a GetSecretValue on the cluster’s rds!cluster-* secret. Individual PostgreSQL connections and statements are in the per-cluster logs exported to CloudWatch Logs; see Observing.
Next steps
Reference
Resource names, IAM scoping, tagging, and the full policy JSON.
Setup
Run the Terraform module and provision the first cluster.

