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