When your organization needs a new AWS account (a new workload environment, a team sandbox, or a specialized service account), you add it to organization-structure.ts and deploy. The landing zone creates the account, moves it into the right OU, and automatically rolls out the account baseline (secure defaults, CloudTrail, and cost controls, plus CDK bootstrap for accounts in the Development and Production OUs) without any manual intervention. Because GuardDuty, Security Hub, Inspector, and Macie are configured org-wide from the security account, a new account is enrolled in whichever of those services you have enabled.
Steps
1. Choose an OU and a unique email address
Pick the OU the new account belongs to. The starter ships with DevelopmentOU and ProductionOU for workload accounts, but any OU in your structure works.
Choose an email address that has never been used for any AWS account globally. The aws+<alias>@<domain> plus-addressing pattern lets you generate unique addresses under a single domain:
aws+payments-prod@example.com
If you already manage multiple accounts under your domain, check your existing accounts first to confirm the address is free.
2. Add the account in organization-structure.ts
Open src/config/organization-structure.ts and add a new entry to the accounts map of the target OU. Keep the account key descriptive and PascalCase. If you publish its ID (see below), the key becomes the stack output name and the TypeScript property name on orgVars:
ProductionOU: {
name: 'workload-prod-ou',
accounts: {
WorkloadAlphaAccount: {
name: 'Workload Alpha',
email: `aws+workload-alpha@${mailDomain}`,
},
// Add your new account here:
PaymentsAccount: {
name: 'Payments',
email: 'aws+payments-prod@example.com',
},
},
},
The name field is the display name shown in the AWS Organizations console. The email is the root email address for the new account.
A workload account like this one needs nothing more. The account-provisioning StackSets target its OU, so it receives the full baseline automatically, and GuardDuty and Macie discover it from AWS Organizations at deploy time. Only add publishAccountIdOutput: true if another stack needs to reference the account by ID through orgVars.PaymentsAccountId. Most workload accounts never do, and leaving it off keeps you well under the CloudFormation output limit.
To attach account-specific SCPs at the same time, add a serviceControlPolicies array to the account entry. See Service Control Policies for the available SCPs and the 10-per-target limit.
3. Preview the change
Run a diff to confirm only the expected resources change before deploying:
pnpm run organization:diff
You should see a new AWS::Organizations::Account resource in the diff output for the LandingZoneOrganizationStack. If you set publishAccountIdOutput: true, you'll also see a new PaymentsAccountId stack output.
4. Deploy
pnpm run organization:deploy
This deploys LandingZoneOrganizationStack to your management account: it creates the account and moves it into the target OU. You do not need to re-run the landing-zone phase for a new workload account. The service-managed baseline StackSets already target its OU, so AWS Organizations auto-deploys their stack instances to the account as soon as it joins.
For CI/CD, push to main and let the generated GitHub Actions workflow handle the deployment. See GitHub Actions Deployment for how that pipeline works.
5. Verify
After the deploy completes, confirm the account exists in AWS Organizations:
aws organizations list-accounts --query 'Accounts[?Name==`Payments`]'
If you opted the account into an ID output with publishAccountIdOutput: true, confirm it was published on the organization stack:
aws cloudformation describe-stacks --stack-name LandingZoneOrganizationStack \
--query 'Stacks[0].Outputs[?OutputKey==`PaymentsAccountId`].OutputValue'
The baseline StackSets run asynchronously after the account is created. Check the StackSet instance status in the CloudFormation console (under StackSets) to confirm the instance for the new account reached CURRENT.
What happens on deploy
LandingZoneOrganizationStack calls the AWS Organizations API to create the account and move it into the target OU. If the account sets publishAccountIdOutput: true, it also gets a PaymentsAccountId stack output that other stacks can consume through orgVars. Otherwise no account ID output is created, and the account is still fully provisioned through its OU.
The SetAlternateContactConstruct and UnsubscribeMarketingMailsConstruct in the same stack detect the new account email and run their automation against the new account: applying your configured billing, security, and operations contacts, and opting the account out of AWS marketing email.
The service-managed StackSets in LandingZoneAccountProvisioningStack target OUs rather than explicit account lists, so AWS Organizations auto-deploys their stack instances to any new account that joins a targeted OU, without any changes to the stack code or a landing-zone redeploy. Quota increase requests are submitted asynchronously; they may take up to 24 hours to be approved by AWS.