The account is the boundary that matters
In AWS, IAM policies can be misconfigured, roles can be over-permissive and tags can be forgotten. An account boundary cannot be crossed by accident. That is why the standard advice, and our own practice, is to separate concerns by account rather than trying to carve one account into safe pieces with permissions alone.
This page explains the layout we typically build as part of a landing zone, why each account exists, and how to avoid overcomplicating it. The rules that govern the accounts are covered in Organizations and SCP guardrails.
What goes wrong in a single-account estate
Single accounts rarely begin as a decision. They accumulate. Typical consequences:
- A developer needs broad rights to test something, and those rights apply to production too.
- CloudTrail logs live in the same account as the people being audited.
- Service quotas, such as vCPU limits, are shared between a load test and the live site.
- The bill is one number, so nobody owns a cost spike.
- A leaked access key exposes everything at once.
None of these is theoretical. They are the common findings in the cloud reviews we run on estates built through the console, which we discuss in our ClickOps inventory and migration plan.
A sensible starting structure
The core accounts
| Account | Purpose | Who touches it |
|---|---|---|
| Management | Organizations, billing, Identity Center | A handful of admins, rarely |
| Log archive | Immutable copy of CloudTrail, Config and similar logs | Read-only for auditors and security |
| Security | GuardDuty, Security Hub and incident tooling delegated admin | Security and platform engineers |
| Shared services | Networking hub, CI runners, artefact registries, DNS | Platform team |
| Workload: production | Customer-facing systems | Deployed by pipeline, limited humans |
| Workload: non-production | Development and staging | Developers |
Many teams add a sandbox organisational unit for experiments with a hard budget and aggressive clean-up, and a break-glass arrangement for emergencies.
The organisational unit tree
Keep it shallow. A typical tree has Security, Infrastructure, Workloads (with Production and Non-Production children) and Sandbox beneath the root. Policies attach at the OU level, so the tree should mirror where your rules actually differ. Every extra level is a place for confusion and a policy inheritance puzzle.
How it works in practice
Creating accounts
Accounts can be created with Control Tower’s Account Factory or directly through Organizations. In Terraform, an account is a small resource:
resource "aws_organizations_account" "prod" {
name = "acme-workload-prod"
email = "[email protected]"
parent_id = aws_organizations_organizational_unit.prod.id
role_name = "OrganizationAccountAccessRole"
lifecycle {
ignore_changes = [role_name]
}
}
The email should be a group mailbox that several people can read, because password resets and AWS notices go there. A personal address becomes a problem the day that person leaves.
Logging that cannot be tampered with
The log archive account holds an S3 bucket receiving the organisation trail and Config data. Its bucket policy lets CloudTrail write but denies deletion, versioning is on, and Object Lock can be enabled where your retention requirements call for it. Workload administrators have no rights there. This is the difference between logs you hope are intact and logs you can show an auditor.
Delegated administration
Rather than logging in to the management account to run security tools, we delegate administration of services such as GuardDuty and Security Hub to the security account. This keeps the management account quiet. The settings behind it are explained in our security baseline page.
Networking
Whether each workload account gets its own VPC or shares a hub through Transit Gateway is a genuine design decision. Our VPC design page covers the trade-offs, including NAT gateway cost.
Decisions and trade-offs
Account per environment or account per application? Environment separation is the minimum. Per-application accounts give stronger isolation and clearer cost, but multiply the overhead. Teams under about twenty engineers usually do well with production and non-production per product line at most.
Control Tower or Organizations directly? Control Tower bundles baselines and is faster to start. Direct Organizations plus Terraform offers more flexibility. See the comparison in our landing zone overview.
Shared services account or not? For a tiny estate it is unnecessary. Once you have a network hub, CI runners or a central container registry, it stops those pieces living in whichever workload account happened to be first.
When not to split further. If a new account would hold three small resources and have no distinct permissions, quotas or compliance need, the overhead of baselines, SSO assignments and budgets outweighs the benefit.
Naming, tagging and ownership
Account names appear in bills, logs, SSO portals and incident chats, so a consistent scheme pays back quickly. We usually use a pattern such as company, purpose, environment (for example acme-workload-prod), and we record an owner, a cost centre and a purpose for every account in a simple registry kept in the repository. Organisation-level tag policies can then require the same tags on resources inside those accounts. The registry also makes retirement easy: when a product is shut down, the account is closed through a documented process rather than abandoned and billed for years.
Common failure modes
- Workloads in the management account. SCPs do not restrict it, and its compromise is catastrophic.
- Account sprawl. Sandbox accounts created freely with no budget or expiry accumulate cost.
- Root emails pointing at individuals. Recovery becomes impossible after staff changes.
- Inconsistent baselines. Accounts created by hand miss logging or alerting. Creating them through code prevents it.
- Cross-account access as an afterthought. Roles are assumed ad hoc, and nobody can say who can reach what.
Delivery and handover
We deliver the structure as Terraform in your repository, with a diagram, a table of accounts and owners, and a short runbook for requesting a new account. We confirm each account receives its baseline, and we remove any scaffolding left over from a previous console-built setup. If you are unsure whether you need this at all, our DevOps maturity assessment gives a quick read.
How to tell it is working
- Each account has a named owner and a stated purpose.
- Costs can be reported per account without tag gymnastics.
- A compromised developer credential cannot reach production.
- Logs from every account arrive in one place within minutes.
- Adding an account takes a pull request and a short review.
To talk through your own structure, contact us.