8 min read

AWS Organizations: put production in its own account

One AWS account feels simpler until dev and prod share a blast radius. Management account hygiene, organizational units, member accounts, and SCPs, in the order you should adopt them.

Terraform architecture and deployment safetyAWSOrganizationsSecurityTerraformDevOps

Most teams start with one AWS account because it is the path of least resistance. Everything lands in the same IAM namespace, the same default VPC, and the same monthly bill. That works until you add a second environment, a security review, or a customer who asks where production data lives. At that point you are not fighting a missing feature. You are fighting the fact that a mistake in staging can reach production credentials, and nobody can prove who changed what across the estate.

AWS Organizations is the control plane for that problem. It does not replace good IAM inside an account. It gives you accounts as blast-radius units, a management account for billing and org-wide guardrails, and service control policies (SCPs) that cap what any identity in a member account can do, even when an administrator gets IAM wrong. I use this layout on multi-environment Terraform platforms and on smaller estates that still need prod to stay prod. Here is the structure that survives the first audit without turning into a landing-zone science project.

Treat the management account as billing, not workloads

When you create an organization, the account you start from becomes the management account (formerly the master account). That account pays the consolidated bill, creates member accounts, attaches SCPs, and integrates with AWS IAM Identity Center if you use it.

The most common early mistake is running application workloads in the management account. Do not. Keep it sparse.

  1. Organization administration and billing contacts.
  2. IAM Identity Center if you centralize human access.
  3. Shared security services only when your design truly requires a single home, such as a centralized log archive account reached through an organization trail.

Everything else belongs in member accounts. A compromised workload role in the management account is an org-wide incident. A compromised role in a sandbox account should stay a sandbox incident.

AWS documents the split in best practices for the management account.

Split environments with accounts, not tags alone

Tags help finance. They do not stop AdministratorAccess in the wrong place.

Give each major environment its own member account when you can afford the operational overhead. A practical minimum for a SaaS team looks like this.

  1. Sandbox — engineers experiment with services and IAM. Accept that it is messy. SCP it hard.
  2. Non-production — shared dev and staging that deploy from CI. No customer data you would regret exporting.
  3. Production — customer traffic, regulated data, and change control.

Optional but valuable:

  1. Security / audit — organization CloudTrail, config aggregators, read-only break-glass roles.
  2. Shared services — DNS, outbound email, or artifacts if you truly centralize them.

Organizational units (OUs) group those accounts so policy attaches once. A layout that scales without ceremony:

Root
├── Security
│   └── Audit (log archive, security tooling)
├── Infrastructure
│   └── Shared (DNS, artifacts, optional networking hub)
└── Workloads
    ├── Sandbox
    ├── NonProd
    └── Prod

You do not need every OU on day one. You do need production in its own account before someone runs terraform destroy against the wrong state file.

Use SCPs as guardrails, not application authorization

An SCP is a policy attached to the organization, an OU, or an account. It filters what all principals in affected accounts can do, including the account root user and administrators. SCPs use the IAM policy grammar, but they only support Deny and Allow effects that limit the maximum available permissions. They never grant permissions by themselves.

That distinction matters. SCPs are not a replacement for least-privilege IAM inside the account. They are the ceiling.

Useful guardrails for most estates:

  1. Deny leaving the organization so a stolen admin cannot exfiltrate the account by removing it from the org.
  2. Deny disabling or deleting organization trails and security services you rely on for audit.
  3. Region allowlist if you operate in one or two regions and want to stop "*" mistakes elsewhere.
  4. Deny root user access keys and discourage root login except break-glass.

Keep the first SCPs short. A deny list of ten services you never use sounds tidy until a legitimate team needs one of them and spends a day decoding AccessDenied. Attach SCPs at the OU level so sandbox can be looser than production.

AWS walks through SCP syntax and inheritance in service control policies. Remember the evaluation order: an explicit Deny in an SCP wins even when IAM says Allow.

Wire human access through Identity Center, not long-lived IAM users

Fifty IAM users with console passwords across three accounts is a credential problem waiting for a spreadsheet leak.

AWS IAM Identity Center (formerly AWS SSO) gives humans short-lived roles into member accounts from one place. Group mappings like PlatformEngineers → AdministratorAccess in NonProd and a tighter role in Prod are easier to audit than per-account users.

For automation, skip static keys entirely. GitHub Actions should assume a role through OIDC, which I cover in deploying to AWS from GitHub Actions with OIDC. Terraform in each account should use its own role with a trust policy scoped to your CI repository and branch.

The pattern is the same everywhere: humans through Identity Center, machines through assumed roles, no standing admin keys in a secrets manager.

Connect accounts without sharing passwords

Member accounts need a way for CI, Terraform, and security tooling to reach them. That means cross-account IAM roles with explicit trust.

A deploy role in the production account trusts only the OIDC provider and sub condition for your repo's production branch. A read-only security role in the audit account trusts only the security tooling account. None of this requires embedding access keys in GitHub.

For Terraform, keep state per account or per environment, the same discipline as splitting ecs-fargate/dev/terraform.tfstate from prod in the ECS Fargate Terraform starter. Organization structure and state layout should tell the same story: a change in dev cannot delete prod.

If you use a shared networking hub, document which account owns the transit gateway or VPC attachments. Organizations gives you the account boundary. You still have to design the peering and routing.

Make consolidated billing useful to finance

Consolidated billing is automatic in an organization. The management account receives one bill. Member accounts still get cost and usage detail, which is what you want for attribution.

Turn on cost allocation tags early. Tag accounts themselves in Organizations with Environment, CostCenter, or Team so Cost Explorer can split spend even before every resource is tagged perfectly. Pair that with the workload changes in cutting your AWS bill with scheduled scale-to-zero so non-production accounts actually reflect idle time on the invoice.

SCPs can also enforce tag-on-create policies in newer setups, but do not let tag enforcement block your first successful deploy. Get accounts and guardrails in place, then tighten tagging once the pipeline is stable.

Know what Organizations does not solve

Organizations organizes accounts and caps permission. It does not replace application-level tenant isolation.

  1. Multi-tenant data inside one account still needs IAM, resource policies, and patterns like S3 Access Points per tenant.
  2. Observability still needs alarms that reach a human, not just a trail in the audit account. Read CloudWatch defaults exist but nobody reads the alarms for the layer above account layout.
  3. Compliance still needs evidence: trails, retention, and runbooks you have tested, not merely more OUs on a diagram.

Treat Organizations as the spine that keeps environments from sharing fate. Everything else still has to work inside each account.

The takeaway

One account is fine for a prototype. It is a poor long-term home for production, staging, and experiments that share admin access.

Create an organization early, keep the management account free of workloads, put production in its own member account, group accounts with OUs, and attach a small set of SCPs that deny the disasters you cannot afford. Wire humans through Identity Center, wire automation through scoped roles, and split Terraform state the same way you split accounts. That is enough structure to pass a serious review without building a full landing zone on week one.

For a platform that ran this pattern across commercial and GovCloud partitions, see six-environment Terraform and GovCloud management.

Frequently asked questions

When should I create an AWS Organization?

Create one before you have production data you care about, or as soon as you add a second environment that should not share IAM with production. Moving later is possible but painful: you will migrate resources, roles, and state rather than greenfield accounts.

What is the difference between an OU and an account?

An account is a hard boundary for billing, service quotas, and IAM. An OU is a folder that holds accounts so you can attach SCPs and policies once to many accounts. OUs do not run workloads by themselves.

Can SCPs grant permissions?

No. SCPs set the maximum permissions available in an account. IAM roles, resource policies, and permission boundaries still do the actual granting inside the account.

Should dev and staging share one account?

Many teams combine dev and staging in one non-production account to reduce overhead. Keep production separate. If staging holds realistic data or production-like secrets, treat it as non-prod with its own SCP ceiling, not as a prefix inside the prod account.

Do I need AWS Control Tower?

No. Control Tower is optional automation for landing zones with opinionated baselines. A manually created organization with OUs, SCPs, Identity Center, and Terraform is enough for many SaaS teams until compliance demands more prescriptive guardrails.

How does this relate to multi-tenant SaaS security?

Organizations separates your environments and your operational accounts. Tenant isolation inside the product still belongs in application design, IAM, and storage boundaries. Use both: accounts for platform separation, Access Points or similar for tenant data.

Comments

    Leave a comment