Organizational Hierarchy Configuration
The Organizational Hierarchy Configuration pattern describes how to structure stacks for enterprise environments with multiple organizations, organizational units (OUs), tenants, and accounts.
Use-cases
Use the Organizational Hierarchy Configuration pattern when:
-
You have one or more organizations with multiple organizational units/departments/tenants
-
Each OU/department/tenant has multiple accounts (dev, staging, prod, etc.)
-
You need to manage configuration at different levels (org, tenant, account)
Benefits
The Organizational Hierarchy Configuration pattern provides the following benefits:
-
Defaults for organizations, tenants/OUs, and accounts are defined in just one place, making the configuration extremely DRY
-
New organizations can be added without affecting existing organization configurations
-
New tenants/OUs can be added to an organization without affecting existing tenants
-
New accounts can be added to a tenant without affecting existing accounts
-
The hierarchical structure mirrors your actual organizational structure, making it intuitive to navigate
Organizational Concepts
Atmos uses context variables to represent different levels of your organizational hierarchy:
namespace- Represents the organization (e.g.,
org1,org2,acme). Used when managing multiple distinct organizations. tenant- Represents an organizational unit, department, or team (e.g.,
core,plat,engineering). Groups related accounts together. stage- Represents an account or deployment stage (e.g.,
dev,staging,prod,audit). Typically maps to an AWS account.
The Role of _defaults.yaml Files
The _defaults.yaml files at each level of the hierarchy contain baseline configurations that are inherited by child levels. These files:
- Must be explicitly imported — they are not automatically included
- Create inheritance chains by importing parent-level defaults
- Are excluded from stack discovery via the
excluded_pathsconfiguration
The _defaults.yaml naming is a convention, not an Atmos feature. The underscore prefix ensures these files sort to the top of directory listings and are visually distinct from stack configurations. See the _defaults.yaml Design Pattern for details.
Example
The following example shows how to structure stacks for an organization (acme) with two OUs (core and plat) and multiple accounts. Each account (stage) is a folder containing layer files that group components by function.
Directory Structure
├── stacks
│ ├── catalog # component defaults
│ │ ├── vpc
│ │ │ └── defaults.yaml
│ │ ├── rds
│ │ │ └── defaults.yaml
│ │ └── eks
│ │ └── defaults.yaml
│ └── orgs
│ └── acme
│ ├── _defaults.yaml
│ ├── core # 'core' OU
│ │ ├── _defaults.yaml
│ │ └── audit
│ │ ├── _defaults.yaml
│ │ └── network.yaml
│ └── plat # 'plat' OU
│ ├── _defaults.yaml
│ ├── dev
│ │ ├── _defaults.yaml
│ │ ├── network.yaml
│ │ └── data.yaml
│ ├── staging
│ │ ├── _defaults.yaml
│ │ ├── network.yaml
│ │ └── data.yaml
│ └── prod
│ ├── _defaults.yaml
│ ├── network.yaml
│ ├── data.yaml
│ └── compute.yaml
│
└── components
└── terraform
├── vpc
├── rds
└── eks
Configure atmos.yaml
atmos.yaml
If you prefer simpler stack names without the layer, use:
name_template: "{{.vars.tenant}}-{{.vars.stage}}"
This works when each layer file defines different components (no overlap).
Configure Organization Defaults
stacks/orgs/acme/_defaults.yaml
Configure Tenant Defaults
stacks/orgs/acme/plat/_defaults.yaml
Configure Stage Defaults
Each stage folder has a _defaults.yaml that sets the stage variable:
stacks/orgs/acme/plat/dev/_defaults.yaml
stacks/orgs/acme/plat/prod/_defaults.yaml
Configure Layer Stacks
Each layer file imports its stage defaults and the relevant component catalogs:
stacks/orgs/acme/plat/dev/network.yaml
stacks/orgs/acme/plat/dev/data.yaml
stacks/orgs/acme/plat/prod/network.yaml
stacks/orgs/acme/plat/prod/compute.yaml
Import Chain
The following diagram shows how configuration flows through the import chain:
Provision the Components
Deploy the network layer in dev:
atmos terraform apply vpc -s plat-dev-network
Deploy the data layer in prod:
atmos terraform apply rds -s plat-prod-data
Deploy the compute layer in prod:
atmos terraform apply eks -s plat-prod-compute
Adding New Elements
Adding a New Account
Create a new stage folder with its defaults and layer files:
stacks/orgs/acme/plat/qa/
├── _defaults.yaml
├── network.yaml
└── data.yaml
Adding a New Layer
Add a new layer file to each stage that needs it:
stacks/orgs/acme/plat/prod/observability.yaml
Combining with Multi-Region
This pattern can be combined with the Multi-Region Configuration pattern. Add the environment variable to your name template and structure:
name_template: "{{.vars.tenant}}-{{.vars.environment}}-{{.vars.stage}}-{{.vars.layer}}"
See the Multi-Region Configuration pattern for details.
Related Patterns
- Layered Stack Configuration - The layer concept used within each stage
- Multi-Region Configuration - Add multi-region support
- _defaults.yaml Convention - The naming convention used throughout
- Component Catalog - Organize reusable component defaults