The AWS landing zone we actually build: what goes in each account

Most multi-account designs fail because nobody agreed what an account is for. Here is the account map we deploy, what lives in each one, and the three guardrails that make it hold.

Every AWS estate we inherit sits somewhere on the same line. At one end, a single account where production, staging and someone's side project share a VPC. At the other, forty accounts created over three years by different people, with no shared logging and four ways of getting credentials. Both are the same problem: the account boundary was never given a job.

An account in AWS is the strongest blast radius you have. Service quotas, IAM, billing and most security controls stop at its edge. So the design question is not "how many accounts", it is "what does this boundary protect".

The account map

This is what we deploy for a mid-size platform team, and it has survived contact with auditors more than once.

  • Management account. Organizations, billing and nothing else. No workloads, no humans with day-to-day access, no Terraform state. It is the account that can dissolve your whole estate, so it stays boring.
  • Log archive. Write-only destination for CloudTrail organization trails, Config, VPC flow logs and ALB logs. Bucket policies deny deletes, object lock is on, and the retention matches whatever your compliance line says.
  • Security tooling. Delegated administrator for GuardDuty, Security Hub, Access Analyzer, Detective and Inspector. The security team gets admin here and read-only everywhere else.
  • Shared networking. Transit Gateway, Route 53 private zones, the VPN or Direct Connect termination, and a centralised egress VPC if you have one. Workload accounts consume subnets through Resource Access Manager and never own the backbone.
  • Shared services. The artefact registry, the CI runners, the golden AMI pipeline, the internal package mirror.
  • One account per workload per environment. payments-prod, payments-staging, analytics-prod. Not one account per team, not one per environment. Per workload per environment.

That last line is where most designs go wrong. A single production account holding eleven services means eleven services share a quota for Lambda concurrency, share an IAM surface, and share the day a misconfigured role gets you paged.

The three guardrails

An account map without controls is just a longer bill. Three things make it hold.

Service control policies, applied to organizational units, not accounts. Keep them few and blunt: deny leaving the organisation, deny disabling CloudTrail or GuardDuty, deny use of regions you do not operate in, deny root user actions outside break-glass. A production OU gets one more: deny deleting log buckets. Resist the urge to write fine-grained permission logic in SCPs; that belongs in IAM roles, and SCP debugging is miserable.

Identity through IAM Identity Center, with no IAM users anywhere. Permission sets map to groups in your identity provider. A developer in payments gets PowerUser in payments-staging and ReadOnly plus a narrow break-glass role in payments-prod. Access keys stop existing; everything else follows from that one change.

A baseline that is code, applied by pipeline. Every new account gets the same starting state: Config recorder on, GuardDuty enabled, default EBS encryption on, S3 public access blocked at account level, a default VPC deleted, and the Terraform execution role created. We run this from a pipeline in a dedicated account, not from a laptop. If account creation is a manual checklist, accounts will drift, and drift is what auditors find.

Terraform layout

One state file per account per layer, remote in S3 with DynamoDB locking, and the backend bucket lives in the account it serves. Cross-account references go through data sources or SSM parameters, never through remote state reads into someone else's file. That rule alone prevents most of the "I ran apply and it deleted their subnet" incidents.

The pipeline assumes a role per account, and that role is the only thing that can write. Humans get read-only in production and raise a PR. It is slower on the first day and much faster on the first incident.

What this costs

Multi-account is not free. Expect more NAT gateways unless you centralise egress, some duplicated security tooling, and a real week of work to move an existing workload. Against that: per-workload cost attribution without tagging heroics, an IAM blast radius you can explain, and a compliance story you do not have to invent at audit time.

If you are migrating from one big account, do it one workload at a time, starting with the least critical, and keep the old account as a shrinking legacy zone rather than trying to empty it in one go. Our cloud consulting work usually starts by drawing the current map, because most teams have never seen theirs on one page — which is exactly what Skyline renders in an afternoon.

What to do this week

Open Organizations and list your accounts. For each one, write a single sentence saying what it protects. The accounts where you cannot finish the sentence are the ones to fix first.

ConsultorIA

Want this done on your cloud?

A ten-day read-only assessment is free, and Skyline lets you see your estate on a map before you write to us.

Related articles

Modules people reuse instead of copying

The two failures are a module that wraps one resource and adds nothing, and a module that does everything and nobody dares change. A minimal interface, safe defaults and honest versioning are what separate them.