When our single AWS account hit a few dozen engineers, everything that could go wrong did: a load test in "prod" knocked over a staging database, a misconfigured IAM policy gave a contractor read access to billing, and nobody could tell which team owned which $2,000-a-month resource. The fix wasn't more IAM policies inside one account, it was splitting into many accounts under AWS Organizations.

This is the structure I landed on, and why it's the sane default rather than over-engineering.

One account per workload-and-environment, not per team

The cleanest blast-radius boundary AWS gives you is the account itself. A mistake in one account can't touch another. So I create separate accounts for prod, staging, and dev of each major workload, plus shared-service accounts. The management (root) account does almost nothing except billing and Organizations administration, no workloads ever run there.

The single most important rule: the management account is sacred. Don't deploy applications into it, don't create human IAM users there. Its only jobs are consolidated billing and managing the org. A breach there is a breach of everything.

Group accounts into OUs that mirror policy, not org chart

Organizational Units exist so you can attach policy to a group of accounts. Structure them around how policy differs, not who reports to whom.

  • Security OU, log archive and audit accounts (centralized CloudTrail, Config, GuardDuty).
  • Infrastructure OU, shared networking, CI/CD, shared tooling.
  • Workloads OU, split into Prod and Non-Prod child OUs with different guardrails.
  • Sandbox OU, loose accounts with hard budget caps for experimentation.

Enforce guardrails with Service Control Policies

SCPs are the teeth of Organizations. They set the maximum permissions any principal in an account can have, even the account's own admin can't exceed them. I use them to deny things that should never happen anywhere, like leaving a region disabled or disabling CloudTrail.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyCloudTrailTampering",
      "Effect": "Deny",
      "Action": [
        "cloudtrail:StopLogging",
        "cloudtrail:DeleteTrail"
      ],
      "Resource": "*"
    },
    {
      "Sid": "DenyOutsideApprovedRegions",
      "Effect": "Deny",
      "NotAction": [ "iam:*", "organizations:*", "support:*" ],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": ["us-east-1", "us-west-2"]
        }
      }
    }
  ]
}

SCPs don't grant anything, they only restrict. You still need IAM permissions inside each account. And remember an SCP attached to an OU applies to every account beneath it, so test against a sandbox OU before rolling to Prod.

Let Control Tower do the heavy lifting

Hand-building all of this, account factory, baseline guardrails, centralized logging, SSO, is weeks of work and easy to get subtly wrong. AWS Control Tower sets up the landing zone for you: it creates the Security OU, log archive and audit accounts, baseline SCPs, and an account factory for vending new accounts consistently. I treat it as the on-ramp and then layer custom SCPs on top.

Centralize identity and billing

Two things should be consolidated from day one. First, identity: use IAM Identity Center (formerly SSO) so people get federated, role-based access across accounts instead of per-account IAM users. Second, billing: consolidated billing rolls every account into one invoice, and, importantly, Savings Plans and RIs purchased in one account apply across the whole org, so volume discounts and commitments are shared.

aws organizations create-account \
  --email "team-payments-prod@example.com" \
  --account-name "payments-prod" \
  --role-name OrganizationAccountAccessRole \
  --tags Key=Environment,Value=prod Key=CostCenter,Value=payments

Tag accounts at creation with environment and cost center so Cost Explorer can attribute spend by account without any further work. Per-account billing is the cleanest cost allocation boundary you'll ever get.

Takeaways

  • Use account boundaries for blast-radius isolation, one account per workload-and-environment.
  • Keep the management account empty of workloads and human users; it does billing and org admin only.
  • Structure OUs around policy differences and enforce non-negotiables with SCPs (tested in a sandbox first).
  • Start with Control Tower, centralize identity in IAM Identity Center, and tag accounts for clean cost allocation.