A single AWS account feels simpler right up until the day a misconfigured IAM policy in a dev experiment can read production data, or a load test in staging exhausts a service quota that production shares, or finance asks what the new product line costs and the honest answer is “somewhere in this one bill.”
Multiple accounts fix all of that, because an AWS account is the strongest isolation boundary AWS offers. IAM permissions, service quotas, billing and blast radius all stop at its edge by default. The trouble is that a dozen accounts managed by hand is its own kind of mess: inconsistent settings, forgotten resources, and a spreadsheet of who has access to what.
The goal is to get the isolation without the operational headache. This is the structure I use, and the automation that makes it cheap to run.
Design the organisation around policy, not the org chart
AWS Organizations groups accounts into organisational units (OUs), and the most important rule is that OUs exist to apply policy. Group accounts by what rules they should share — how strict, how monitored, what’s allowed — not by which department owns them. Departments reorganise; a production workload is a production workload whoever runs it.
The shape I start with:
- Management account — runs Organizations, billing and little else. No workloads, very few humans. Service control policies don’t apply to it, which is exactly why nothing should run there.
- Security OU — a log archive account that receives organisation-wide CloudTrail and Config data and that almost nobody can write to, and a security tooling account that is the delegated administrator for GuardDuty, Security Hub and similar services.
- Infrastructure OU — shared networking (Transit Gateway, centralised egress, DNS) and shared services such as CI runners or artifact repositories.
- Workloads OU — split into production and non-production OUs, with each application or team getting its own accounts per environment.
- Sandbox OU — personal or team experimentation accounts with generous freedom, tight budgets, no connectivity to anything real, and an expiry date.
It’s also worth having a suspended OU with a deny-all policy for accounts being decommissioned, and a policy staging OU for testing new guardrails before they’re applied everywhere.
Guardrails that nobody has to remember
The value of an organisation is that rules are enforced centrally, once, instead of configured account by account. There are two kinds of guardrail, and you want both.
Preventive guardrails make the wrong thing impossible. Service control policies set the maximum permissions available in the accounts they’re attached to — they never grant anything themselves, but no IAM policy inside the account can exceed them. My baseline set denies:
- leaving the organisation;
- disabling or modifying the organisation’s CloudTrail, GuardDuty and Config;
- using regions we don’t operate in;
- actions by the root user of member accounts;
- creating IAM users with long-lived access keys, where identity is centralised.
A region guardrail, for example, has to exempt the global services that are homed in us-east-1:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnapprovedRegions",
"Effect": "Deny",
"NotAction": [
"iam:*", "organizations:*", "sts:*", "support:*",
"cloudfront:*", "route53:*", "budgets:*", "waf:*"
],
"Resource": "*",
"Condition": {
"StringNotEquals": { "aws:RequestedRegion": ["eu-west-1", "us-east-1"] }
}
},
{
"Sid": "ProtectOrgTrail",
"Effect": "Deny",
"Action": ["cloudtrail:StopLogging", "cloudtrail:DeleteTrail", "cloudtrail:UpdateTrail"],
"Resource": "*",
"Condition": {
"ArnNotLike": { "aws:PrincipalArn": "arn:aws:iam::*:role/OrgSecurityAdmin" }
}
}
]
}
Test new SCPs in the policy-staging OU first. A deny that’s slightly too broad at the root can break every account at once.
Detective guardrails catch what prevention can’t express: a public S3 bucket, an unencrypted volume, a security group open to the world. AWS Config rules and Security Hub standards, aggregated into the security tooling account, give you one view of every finding across every account — and one place to route them to the owning team.
The best security control is the one a tired engineer can’t accidentally bypass.
One identity, many accounts
Many accounts must not mean many logins. Use IAM Identity Center connected to your identity provider, so people sign in once and assume a role in whichever account they need.
- Permission sets define what a role can do — read-only, developer, operator, admin — and are assigned to groups per account. Access is granted by adding someone to a group in the identity provider, and revoked the same way when they leave.
- No IAM users for humans. Short-lived credentials from Identity Center replace long-lived access keys entirely.
- CI deploys through roles too. Pipelines authenticate with OIDC federation and assume a deploy role in the target account. No stored cloud credentials in the CI system.
- Break-glass access exists and is watched. A small number of emergency roles, stored securely, with every use raising an alert.
Centralise the things that must be consistent
Some capabilities should exist exactly once, owned by a platform team, and be consumed by every account.
- Logging. An organisation-wide CloudTrail delivering to the log archive account, into an S3 bucket with Object Lock, so audit logs can’t be altered even by someone with admin in a workload account.
- Networking. Plan IP ranges centrally — VPC IPAM helps — so account networks never overlap and can always be connected later. Connect VPCs through a Transit Gateway in the network hub, and centralise internet egress where you need inspection. Watch the data-processing charges on shared NAT and inspection paths; centralised egress is a cost line, not just a diagram.
- Security services. GuardDuty, Security Hub, IAM Access Analyzer and friends enabled organisation-wide from the delegated administrator account, automatically including every new account.
- Cost visibility. Every account belongs to an owner and a cost centre, recorded as account tags. Budgets are created per account at vending time, so the first alert doesn’t depend on someone remembering to set one up.
Make a new account boring
The operational headache people fear comes from treating account creation as a project. The fix is to make it a product: an automated account-vending pipeline that takes a request — owner, environment, cost centre, OU — and returns a fully baselined account in minutes.
Whether you build on AWS Control Tower’s Account Factory or your own pipeline using Organizations and infrastructure as code, the new account should arrive with:
- its place in the right OU, inheriting the right SCPs;
- Identity Center groups and permission sets already assigned;
- logging, Config and security services enabled and reporting centrally;
- a network baseline — VPC from the IPAM pool, attached to the hub if it needs connectivity;
- a budget with alerts routed to the owner;
- a deploy role trusted by CI.
When a new environment is a pull request and a coffee break rather than a week of tickets, teams stop cramming unrelated workloads into existing accounts — and the isolation you designed actually happens.
The checklist I use when reviewing a multi-account setup:
- The management account runs the organisation and nothing else.
- OUs group accounts by shared policy, not by department.
- SCPs protect logging and security services, restrict regions and block the root user — and are tested before rollout.
- Detective controls report every account into one security view.
- People and pipelines use short-lived, federated credentials; there are no long-lived keys.
- Audit logs land in a separate, locked-down log archive account.
- IP ranges are planned centrally and never overlap.
- New accounts are vended automatically with the full baseline, a budget and an owner.
Done well, none of this slows teams down. It’s what lets you say yes to a new team, a new product or a risky experiment — knowing a mistake in one account stays in that account.