- Published on
AWS Multi-Account Architecture: Why One Account Is Never Enough
- Authors

- Name
- Benjamin Lee
Why Multiple Accounts?
AWS itself is direct about this: using multiple accounts to isolate and manage business applications and data helps you optimize across most of the Well-Architected Framework pillars — operational excellence, security, reliability, and cost optimization. An AWS account is the fundamental isolation boundary for identity, access management, and billing. Resources in one account cannot access resources in another by default.
A single account means a single blast radius. A compromised credential, a runaway cost spike, or a misconfigured S3 bucket can affect everything. The fix isn't complicated, but it does require setting things up deliberately.
The Organizational Structure
AWS Organizations lets you group accounts into Organizational Units (OUs). The key design principle: OUs should be based on function and required controls, not your org chart.
A practical starting structure:
Root
├── Security OU
│ ├── Log Archive Account (centralized CloudTrail, S3 access logs)
│ └── Audit Account (Security Hub, GuardDuty, Config aggregator)
├── Infrastructure OU
│ └── Shared Services Account (CI/CD, artifact registries, DNS)
├── Workloads OU
│ ├── Development Account
│ ├── Staging Account
│ └── Production Account
└── Sandbox OU
└── Individual developer sandbox accounts
The Security OU is special — AWS Control Tower provisions a Log Archive and an Audit account automatically, and recommends keeping them clean, meaning no non-security workloads land there.
Setting Up with Control Tower
AWS Control Tower automates the baseline: it provisions your management account, Log Archive, and Audit accounts, wires up CloudTrail and AWS Config across all accounts, and sets up IAM Identity Center for federated access. The official guidance is to use Control Tower as your starting point and extend from there with custom SCPs and Account Factory for Terraform (AFT).
Account Factory for Terraform lets you define new accounts as code:
module "staging_account" {
source = "aws-ia/control_tower_account_factory/aws"
version = "~> 1.0"
account_name = "workload-staging"
account_email = "aws+staging@yourcompany.com"
organizational_unit_name = "Workloads"
sso_user_email = "admin@yourcompany.com"
}
This makes account provisioning repeatable, auditable, and fast — a new isolated account in minutes instead of days.
Service Control Policies That Actually Matter
SCPs define the ceiling of what any IAM principal in an account can do, regardless of their own permissions. They don't grant access — they restrict it. AWS recommends applying less granular policies higher in the OU hierarchy and tightening them as you move to leaf accounts.
Three SCPs worth applying from day one:
Require MFA for sensitive actions:
{
"Effect": "Deny",
"Action": ["iam:DeletePolicy", "iam:DeleteRole", "iam:AttachRolePolicy"],
"Resource": "*",
"Condition": {
"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}
}
}
Block root account usage:
{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringLike": {"aws:PrincipalArn": "arn:aws:iam::*:root"}
}
}
Restrict to approved regions:
{
"Effect": "Deny",
"NotAction": ["iam:*", "organizations:*", "support:*"],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": ["us-east-1", "us-west-2"]
}
}
}
Apply these at the Root or at the Workloads OU level — not per account. That's the point: write the rule once, enforce it everywhere below.
Cross-Account Access
For human access, IAM Identity Center (successor to AWS SSO) is the right answer. Define permission sets, assign them to accounts, and users get time-limited credentials scoped to exactly what they need. No long-lived IAM users, no shared credentials.
For CI/CD and service-to-service access, use IAM roles with OIDC trust. GitHub Actions, for example:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ secrets.PROD_ACCOUNT_ID }}:role/GitHubDeploy
aws-region: us-east-1
The trust policy on that role scopes it to a specific GitHub repo and branch — no secret rotation required, no long-lived keys at risk.
The Payoff
The blast radius of a credential compromise in a multi-account setup is one account — and SCPs further constrain what an attacker can do even within that account. Billing is isolated by account, so cost anomalies surface immediately. Developers can experiment freely in sandboxes without touching production infrastructure.
The overhead to set this up with Control Tower is measured in days. The overhead to migrate a tangled single-account setup later is measured in months. Set it up first.
Sources:
- Organizing Your AWS Environment Using Multiple Accounts — AWS Whitepapers
- Best Practices for AWS Organizations SCPs — AWS Industries Blog
- Managing Multi-Account Environments with Control Tower — AWS Cloud Operations Blog
- AWS Security Maturity Model: Multi-Account Management