Why account boundaries, not just VPC boundaries
A VPC is a network boundary. An AWS account is a blast-radius, quota, billing, and IAM boundary. These are different axes, and conflating them is how a single compromised IAM role in a “shared” account takes down prod, staging, and the data warehouse in one incident.
Four concrete reasons account separation beats VPC-only separation:
- Blast radius. An over-permissioned IAM role, a leaked access key, or a misconfigured S3 bucket policy is scoped to the account. Cross-account access requires an explicit trust relationship — it doesn’t happen by default the way cross-VPC access within one account’s IAM boundary can.
- Service quotas are account-level (and often Region-level within the account). EC2 vCPU limits, VPC counts, Lambda concurrent executions — these are tracked per account per Region. Lambda is the clearest example: the 1,000 concurrent-executions default quota applies per Region and is shared across every function in that account’s Region (Lambda quotas, AWS docs), so two teams in one account share one throttle. One noisy team hitting a quota ceiling in a shared account can starve every other team’s deployments. Separate accounts give each team (or environment) its own quota pool.
- Billing clarity. Account-level billing gives you clean cost attribution without relying on tagging discipline, which — honestly — degrades over time no matter how good your tagging policy looks on paper. An account boundary is a cost boundary nobody can forget to apply.
- IAM boundary as a backstop, not the only control. You should still write least-privilege IAM policies inside each account. But account separation means a policy mistake is contained, rather than being the only thing standing between a dev engineer’s role and the production RDS instance.
None of this means VPC design stops mattering — you still need the subnet and routing discipline described elsewhere in this reference. It means VPC isolation inside one account is not a substitute for account isolation, because IAM and quotas don’t respect VPC boundaries.
Organizations, OUs, and SCPs: the control plane
AWS Organizations gives you a management account plus member accounts arranged into Organizational Units (OUs) — a tree structure you use to group accounts by function or environment, not by org chart.
A workable OU structure, usable as a starting point:
Root
├── Security OU (log archive, security tooling accounts)
├── Infrastructure OU (network account, shared services)
├── Workloads OU
│ ├── Production OU
│ ├── Staging OU
│ └── Development OU
└── Sandbox OU (individual experimentation, auto-expiring)
Service Control Policies (SCPs) attach to OUs and set the maximum permissions available to every account and every IAM principal beneath that OU — AWS states flatly that “no permissions are granted by an SCP,” and that effective permissions are the intersection of the SCP and the identity-based and resource-based policies (Service control policies, AWS docs). This is the piece that actually enforces your boundaries instead of just documenting them — with two gaps you must design around, because neither is intuitive:
- SCPs have no effect on users or roles in the management account. They “affect only the member accounts in your organization,” and that remains true for a member account designated as a delegated administrator when acting from the management account. This is the structural reason the management account should run no workloads and hold no day-to-day human access.
- SCPs do not affect service-linked roles. A guardrail that assumes it covers every principal in an account does not.
SCPs do apply to a member account’s root user, which is what makes them usable as a root guardrail. Examples that earn their place in most landing zones:
- Deny leaving the Organization, deny disabling CloudTrail, deny deleting the log archive bucket — applied at the root, inherited everywhere.
- Deny use of regions you don’t operate in (reduces attack surface and accidental cost from a resource spun up in an unexpected region).
- In the Sandbox OU: deny anything that isn’t EC2/S3/basic compute, and cap instance sizes, so experimentation can’t produce a surprise bill or a persistent resource nobody tracks.
SCPs are the mechanism that makes “developers can’t touch production IAM” an enforced fact rather than a policy document. Write them sparingly and test them in a non-critical OU first — AWS’s own guidance is to avoid attaching an SCP at the organization root “without thoroughly testing the impact,” and to move accounts into a test OU one at a time. An overly broad deny can lock out break-glass access you need during an incident, which is its own kind of outage. Related trap: do not detach the default FullAWSAccess policy without replacing it, or every AWS action from member accounts fails.
Account vending: how new accounts actually get created
“Account vending” is the automated pipeline that creates a new account, drops it into the right OU, applies baseline SCPs, sets up the baseline IAM roles (including a break-glass admin role trusted by the management account), configures logging and security tooling integration, and hands the result to a team — ideally in minutes, not a ticket queue measured in days. Control Tower’s built-in implementation is Account Factory, “a configurable account template that helps to standardize the provisioning of new accounts with pre-approved account configurations,” built on AWS Service Catalog; a custom landing zone builds the equivalent in IaC.
The baseline every vended account should get on day one, regardless of tooling:
- CloudTrail (organization trail, centrally logged — don’t rely on each account configuring its own)
- Config (for drift and compliance recording)
- GuardDuty / security tooling delegated to the security account
- A standard set of IAM roles with SSO-based access (IAM Identity Center), not long-lived IAM users
- Budget alerts and a default service quota increase request where you know a workload will need it
Control Tower vs building your own
| AWS Control Tower | Custom landing zone (Terraform/CDK + Organizations API) | |
|---|---|---|
| Time to first account | Fast — AWS states it “orchestrates the capabilities of several other AWS services, including AWS Organizations, AWS Service Catalog, and AWS IAM Identity Center, to build a landing zone in less than an hour” (What is AWS Control Tower, AWS docs) | Slower — you design and build the pipeline first |
| Flexibility | Constrained to Control Tower’s control model and supported account structures — though you can extend the environment by working directly in Organizations and then update the landing zone to reflect it | Full control over every SCP, every baseline resource, every naming convention |
| Guardrails | Pre-built controls in three kinds — preventive, detective, and proactive — each carrying guidance of mandatory, strongly recommended, or elective | You write and maintain every guardrail yourself |
| Drift handling | Control Tower detects and flags drift from its baseline | You own drift detection — typically via Config rules or policy-as-code |
| Best fit | Teams that want a standard landing zone fast and are comfortable with AWS’s opinions | Teams with existing IaC maturity, non-standard requirements, or who need guardrails Control Tower doesn’t model |
Honest take: for most organizations starting fresh, Control Tower is the right default. It encodes a lot of hard-won landing zone design in a maintained product, and the guardrails it ships cover the mistakes that actually happen. Build your own landing zone when you have specific requirements Control Tower doesn’t support cleanly, or when you’re already deep in Terraform/CDK and the team would rather own every piece than learn Control Tower’s abstractions. Don’t build your own purely because “we might need the flexibility someday” — that flexibility has an ongoing maintenance cost, paid by whoever’s on call for the account-vending pipeline.
Centralized logging and security tooling: dedicated accounts, not a shared “ops” account
Two accounts do heavy lifting in almost every landing zone:
- Log archive account — the destination for the organization CloudTrail trail, Config recordings, VPC Flow Logs, and application logs you centralize. Nothing else runs here. Write-once semantics protect log integrity even from an account compromise elsewhere in the org — but be specific about the mode: S3 Object Lock requires versioning, and only compliance mode resists deletion “by any user, including the root user in your AWS account,” whereas governance mode is bypassable by a principal holding
s3:BypassGovernanceRetention(S3 Object Lock, AWS docs). For an audit trail you may one day need to defend, that is the whole control. - Security tooling account — GuardDuty, Security Hub, and any SIEM/SOAR integration, delegated administrator for these services across the Organization. Security engineers get access here; workload teams don’t.
Resist the temptation to fold these into a general “shared services” or “ops” account that also runs your CI/CD runners, your internal tools, and your VPN concentrator. Logging and security tooling need the tightest access control in the entire Organization — mixing them with general infrastructure means your CI/CD pipeline’s IAM role has a plausible path toward tampering with the evidence trail that would catch it.
Network account patterns
A dedicated network account (sometimes split into a “transit” or “connectivity” account) owns the Transit Gateway, the Direct Connect gateway, VPN connections, and often a centralized egress VPC. Workload accounts attach their VPCs to the shared TGW rather than each managing their own internet egress or on-prem connectivity path.
This buys you: one place to audit all cross-account and on-prem routing, one team responsible for the hub, and centralized egress inspection (route everything through a shared NAT or firewall VPC before it hits the internet) without every workload team reinventing it. The cost is a dependency — every workload account’s connectivity now depends on the network account’s TGW route tables being correct, so changes there need the same change-control rigor as a core router in a traditional data center.
When one account is genuinely fine
Here’s the part most landing zone content won’t say: if you’re a small team — a handful of engineers, one or two production workloads, no regulatory requirement forcing segregation — a full multi-account Organization with Control Tower, dedicated security and log archive accounts, and a network hub account is over-engineering. You will spend real time building and maintaining a landing zone whose guardrails protect you from organizational failure modes (large, cross-functional teams stepping on each other) that don’t exist yet at your scale.
A single account with disciplined IAM (least privilege, no shared root credentials, SSO-based access), separate VPCs or even separate regions for prod/non-prod, and basic CloudTrail/Config logging gets you most of the safety with a fraction of the operational overhead. Move to multi-account when you actually feel the pain this pattern solves: a second team whose blast radius you need to contain, a compliance requirement naming account-level segregation specifically, or quota contention between workloads that a single account’s limits can’t absorb. Building the landing zone before you have that pain means maintaining infrastructure that protects against a problem you don’t have yet, at the expense of the problem you do have — shipping product.