Skip to main content

Mixins

Atmos Design Pattern

Mixins are reusable configuration fragments that encapsulate settings you want to apply consistently. Instead of repeating the same values across multiple stacks, define them once in a mixin and import where needed.

Use-cases

Use Mixins when:

  • You repeat the same configuration across multiple stacks

  • You want region-specific defaults (availability zones, region name)

  • You want stage-specific defaults (instance sizes, feature flags)

  • Different teams should share consistent settings

Two Places for Mixins

Mixins can live in two locations depending on their scope:

LocationScopeExamples
stacks/mixins/Global settings that apply across many componentsRegion defaults, stage defaults, tenant defaults
stacks/catalog/<component>/mixins/Component-specific feature flags and versionsvpc/mixins/multi-az, eks/mixins/1.27

Common Global Mixin Types

Mixin TypeContainsExample
RegionRegion name, AZs, environment abbreviationmixins/region/us-east-2.yaml
StageStage name, stage-specific defaultsmixins/stage/prod.yaml
TenantTeam/OU name, team-specific settingsmixins/tenant/platform.yaml

Example: Region Mixins

Region mixins encapsulate everything that's consistent for a region:

stacks/mixins/region/us-east-2.yaml

vars:
region: us-east-2
environment: ue2

# Region-specific component defaults
components:
terraform:
vpc:
vars:
availability_zones:
- us-east-2a
- us-east-2b
- us-east-2c

stacks/mixins/region/us-west-2.yaml

vars:
region: us-west-2
environment: uw2

components:
terraform:
vpc:
vars:
availability_zones:
- us-west-2a
- us-west-2b
- us-west-2c

Now stacks import the region mixin instead of repeating these values:

stacks/deploy/us-east-2/dev.yaml

import:
- mixins/region/us-east-2
- catalog/vpc/defaults

vars:
stage: dev

components:
terraform:
vpc:
vars:
ipv4_primary_cidr_block: "10.10.0.0/16"

Example: Stage Mixins

Stage mixins define defaults for each environment:

stacks/mixins/stage/dev.yaml

vars:
stage: dev

# Dev defaults: smaller, cheaper
components:
terraform:
vpc:
vars:
nat_gateway_enabled: false
max_subnet_count: 2
rds:
vars:
instance_class: db.t3.small

stacks/mixins/stage/prod.yaml

vars:
stage: prod

# Prod defaults: full configuration
components:
terraform:
vpc:
vars:
map_public_ip_on_launch: false
rds:
vars:
instance_class: db.r6g.xlarge
multi_az: true

Example: Catalog Mixins (Feature Flags)

Mixins inside a component's catalog folder enable optional features:

stacks/catalog/vpc/mixins/multi-az.yaml

components:
terraform:
vpc:
vars:
max_subnet_count: 3
availability_zones_count: 3

stacks/catalog/vpc/mixins/nat-gateway.yaml

components:
terraform:
vpc:
vars:
nat_gateway_enabled: true
nat_instance_enabled: false

Stack files pick the features they need:

stacks/deploy/prod.yaml

import:
- catalog/vpc/defaults
- catalog/vpc/mixins/multi-az # Enable multi-AZ
- catalog/vpc/mixins/nat-gateway # Enable NAT gateway

vars:
stage: prod

Example: Catalog Mixins (Versions)

Version mixins are perfect for components like EKS where different clusters may run different versions:

stacks/catalog/eks/mixins/1.27.yaml

components:
terraform:
eks/cluster:
vars:
cluster_kubernetes_version: "1.27"
addons:
vpc-cni:
addon_version: "v1.12.6-eksbuild.2"
kube-proxy:
addon_version: "v1.27.1-eksbuild.1"
coredns:
addon_version: "v1.10.1-eksbuild.1"

stacks/catalog/eks/mixins/1.28.yaml

components:
terraform:
eks/cluster:
vars:
cluster_kubernetes_version: "1.28"
addons:
vpc-cni:
addon_version: "v1.14.1-eksbuild.1"
kube-proxy:
addon_version: "v1.28.1-eksbuild.1"
coredns:
addon_version: "v1.10.1-eksbuild.4"

Upgrade clusters independently by changing which version mixin they import:

stacks/deploy/prod/us-east-2.yaml

import:
- catalog/eks/defaults
- catalog/eks/mixins/1.28 # This cluster is on 1.28

stacks/deploy/prod/us-west-2.yaml

import:
- catalog/eks/defaults
- catalog/eks/mixins/1.27 # This cluster is still on 1.27

Import Order Matters

Later imports override earlier ones. Order from general to specific:

import:
- catalog/vpc/defaults # 1. Component defaults (most general)
- catalog/vpc/mixins/multi-az # 2. Feature flags
- mixins/region/us-east-2 # 3. Region settings
- mixins/stage/prod # 4. Stage settings (most specific)

Directory Structure

stacks/
├── catalog/ # Component defaults
│ ├── vpc/
│ │ ├── defaults.yaml
│ │ └── mixins/ # Component-specific mixins
│ │ ├── multi-az.yaml
│ │ └── nat-gateway.yaml
│ └── eks/
│ ├── defaults.yaml
│ └── mixins/ # Version mixins
│ ├── 1.27.yaml
│ └── 1.28.yaml
├── mixins/ # Global mixins
│ ├── region/
│ │ ├── us-east-2.yaml
│ │ └── us-west-2.yaml
│ └── stage/
│ ├── dev.yaml
│ ├── staging.yaml
│ └── prod.yaml
└── deploy/ # Top-level stacks
└── us-east-2/
├── dev.yaml
└── prod.yaml

Before and After

Without mixins (repetitive):

stacks/deploy/us-east-2/dev.yaml
vars:
region: us-east-2
environment: ue2
stage: dev

components:
terraform:
vpc:
vars:
availability_zones: [us-east-2a, us-east-2b, us-east-2c]
nat_gateway_enabled: false
stacks/deploy/us-east-2/prod.yaml
vars:
region: us-east-2
environment: ue2
stage: prod

components:
terraform:
vpc:
vars:
availability_zones: [us-east-2a, us-east-2b, us-east-2c]
map_public_ip_on_launch: false

With mixins (DRY):

stacks/deploy/us-east-2/dev.yaml
import:
- mixins/region/us-east-2
- mixins/stage/dev
- catalog/vpc/defaults
stacks/deploy/us-east-2/prod.yaml
import:
- mixins/region/us-east-2
- mixins/stage/prod
- catalog/vpc/defaults

References