Version Management Patterns -- Detailed Reference
This reference covers versioning strategies, implementation details, and decision guidance for managing component versions in Atmos.
Core Concepts
Deployment vs Release
- Deployment: Declaring that an environment should converge to a specific version (target state).
- Release: Actually updating the environment to that version (applying the change).
Versioning Schemes
Two broad categories of naming conventions:
Number-Based (Fixed Points) -- immutable version identifiers:
- SemVer (
1.2.3) -- MAJOR.MINOR.PATCH, communicates change impact - CalVer (
2024.10.1) -- date-based, temporal tracking - Sequential (
v1,v2) -- simple incrementing numbers - Major/Minor (
1.0,2.0) -- simplified SemVer
Label-Based (Moving Targets) -- stage identifiers that evolve:
- Maturity Levels (
alpha,beta,stable) -- stability indicators - Environment Names (
dev,staging,prod) -- deployment stage alignment
| Pattern | Best Versioning Scheme |
|---|---|
| Strict Version Pinning | SemVer, CalVer, Sequential |
| Release Tracks/Channels | Maturity Levels, Environment Names |
| Git Flow | Environment Names (branches ARE environments) |
| Folder-Based Versioning | Simple naming, Sequential |
Continuous Version Deployment
The recommended trunk-based strategy. All environments work from the main branch, converging through progressive automated rollout.
How It Works
- All stack configurations reference the same component path (no version qualifiers)
- Changes merge to main branch
- CI/CD pipeline deploys progressively: dev -> staging -> prod
- Environments naturally diverge during rollout, then converge when pipeline completes
Configuration
# All environments reference the same componentcomponents:terraform:vpc:metadata:component: vpc # Same for dev, staging, prodvars:environment: prodcidr_block: "10.2.0.0/16"
Divergence Model
Time 0: Commit merged to mainDev: new commit (deployed automatically)Staging: previous commit (operational divergence)Prod: previous commitTime +30min: Dev validatedStaging: new commit (deployed after dev passes)Time +2hrs: Staging validated, manual approvalProd: new commit (convergence achieved)
This operational divergence is expected, time-bound, and automatically converging.
Folder-Based Versioning
The foundational approach for organizing components with explicit folder structure.
Directory Structure
components/terraform/vpc/v1/ # Version 1 implementationmain.tfvariables.tfoutputs.tfv2/ # Version 2 implementationmain.tfvariables.tfoutputs.tfMIGRATION.mdv3-preview/ # Version 3 in developmentmain.tfvariables.tf
Stable Workspace Keys
Use metadata.name to ensure Terraform state remains stable across version upgrades:
components:terraform:vpc:metadata:name: vpc # Stable logical identity (workspace key)component: vpc/v2 # Physical version path (can change)# Result: workspace_key_prefix = "vpc" (stays same when upgrading to v3)
Priority order for workspace key calculation:
- Explicit backend config (
backend.s3.workspace_key_prefix) metadata.name(recommended)metadata.component- Atmos component name (YAML key)
Migration Strategy
Roll out new versions progressively:
# Week 1: Developmentdev:vpc:metadata:component: vpc/v2# Week 2: Stagingstaging:vpc:metadata:component: vpc/v2# Week 3-4: Productionprod:vpc:metadata:component: vpc/v2
Rollback
Switch the folder reference back. Since old version folder still exists, rollback is instantaneous:
vpc:metadata:component: vpc/v1 # Was: vpc/v2
No state migration needed when using stable metadata.name.
Release Tracks/Channels
Named channels that environments subscribe to. Promotes tracks instead of individual pins.
Two Organizational Approaches
Component-Centric (vpc/alpha/, vpc/beta/, vpc/prod/):
- Each component has its own tracks
- Independent component evolution
- Best when components have independent release cycles
Track-Centric (alpha/vpc/, beta/vpc/, prod/vpc/):
- All components grouped by track
- Cohesive promotion (all components move together)
- Best when components are tightly coupled
Configuration
# stacks/catalog/vpc.yamlcomponents:terraform:vpc/defaults:metadata:type: abstractname: vpc # Stable identity# stacks/prod/us-east-1.yamlcomponents:terraform:vpc:metadata:inherits: [vpc/defaults]component: prod/vpc # Subscribe to production track
Promotion Workflow
- New version lands in alpha track
- After validation, promote to beta track (update vendor.yaml, run
atmos vendor pull) - After staging validation, promote to prod track
- All environments on that track converge to the new version
Vendoring to Tracks
# vendor.yamlspec:sources:- component: vpc-alphasource: "git::https://github.com/acme/components.git//vpc?ref=v1.14.0"targets:- "components/terraform/alpha/vpc"- component: vpc-prodsource: "git::https://github.com/acme/components.git//vpc?ref=v1.12.8"targets:- "components/terraform/prod/vpc"
Each channel MUST be vendored to a distinct path. Vendoring multiple channels to the same path causes the last one to overwrite all others.
Strict Version Pinning
Explicit SemVer versions for maximum control and audit trail.
Configuration
# vendor.yamlspec:sources:- component: vpcsource: "github.com/acme/components.git//modules/vpc?ref={{.Version}}"version: "v1.12.3"targets:- "components/terraform/vpc/{{.Version}}"# stacks/catalog/vpc.yamlcomponents:terraform:vpc/defaults:metadata:type: abstractname: vpc# stacks/prod/us-east-1.yamlcomponents:terraform:vpc:metadata:inherits: [vpc/defaults]component: vpc/v1.12.3
Trade-offs
Benefits:
- Clear audit trail of exact versions
- Simplified rollback (change pin to previous version)
- Regulatory compliance
Drawbacks:
- Environments naturally drift without constant updates
- Problems surface late in promotion cycle
- Cannot safely skip versions during promotion
- PR storms from automated dependency update tools
Source-Based Version Pinning
Per-environment version control using the source field directly in stack configuration.
String Form
components:terraform:vpc:source: "github.com/org/components//modules/vpc?ref=1.450.0"vars:cidr_block: "10.0.0.0/16"
Map Form (Full Control)
components:terraform:vpc:source:uri: github.com/org/components//modules/vpcversion: 1.450.0included_paths:- "*.tf"- "modules/**"excluded_paths:- "*.md"- "tests/**"vars:cidr_block: "10.0.0.0/16"
Version Inheritance
Define source defaults in catalog, override versions per environment:
# stacks/catalog/vpc/defaults.yamlcomponents:terraform:vpc/defaults:metadata:type: abstractsource:uri: github.com/org/components//modules/vpcversion: 1.450.0# stacks/dev/us-east-1.yaml (override version only)components:terraform:vpc:metadata:inherits: [vpc/defaults]source:version: 1.451.0 # Latest in dev
When to Use Source vs Vendoring
| Requirement | Source | Vendoring |
|---|---|---|
| No vendor manifest files | Yes | No |
| Code review of dependencies | No | Yes |
| Offline deployment | No | Yes |
| Local modifications | No | Yes |
| Audit trail in Git | No | Yes |
| AI coding assistant context | No | Yes |
| Minimal operational overhead | Yes | No |
Vendoring Component Versions
Automates copying components from external sources into your repository.
Basic Configuration
# vendor.yamlapiVersion: atmos/v1kind: AtmosVendorConfigmetadata:name: component-vendoringspec:sources:- component: vpcsource: "github.com/cloudposse/terraform-aws-vpc.git///?ref={{.Version}}"version: "2.1.0"targets:- "components/terraform/vpc"included_paths:- "**/*.tf"- "**/*.tfvars"- "README.md"excluded_paths:- "examples/**"- "test/**"
Template Variables
| Variable | Description |
|---|---|
{{.Component}} | Component name from component: field |
{{.Version}} | Version from version: field |
{{.Source}} | Full source URL |
Commands
atmos vendor pull # Pull all componentsatmos vendor pull --component vpc # Pull specific componentatmos vendor pull --component vpc --version 2.2.0 # Specific versionatmos vendor pull --dry-run # Preview changes
Divergence Management
When intentionally diverging from upstream:
- Make local changes directly in vendored folder
- Comment out or remove the component from
vendor.yaml - Create
LOCAL_MODIFICATIONS.mddocumenting changes - Re-enable vendoring when ready to reconverge
Git Flow: Branches as Channels
Branch-based alternative where long-lived branches map to release channels.
Branch Structure
main (integration branch)channels/prod # Production channelchannels/staging # Staging channelchannels/dev # Development channelfeature/* # Feature branches
Vendoring from Branches
Each channel must be vendored to a distinct path:
# vendor.yamlspec:sources:- component: vpc-devsource: "git::https://github.com/acme/infra.git//components/terraform/vpc?ref=channels/dev"targets:- "components/terraform/channels/dev/vpc"- component: vpc-prodsource: "git::https://github.com/acme/infra.git//components/terraform/vpc?ref=channels/prod"targets:- "components/terraform/channels/prod/vpc"
Stack Configuration
# stacks/prod/us-east-1.yamlcomponents:terraform:vpc:metadata:inherits: [vpc/defaults]component: channels/prod/vpc
When to Use
- Team already practices Git Flow
- Need centralized promotion control through pull requests
- Require clear audit trails via merge history
- Want approval gates for promotions
Choosing a Strategy
Decision Factors
- Roll Forward vs Rollback: Culture of fixing forward or requiring rollback?
- Team Size: Strict pinning becomes painful as environment count grows.
- Release Cadence: High-frequency updates favor convergent patterns.
- Third-Party Dependencies: Heavy external usage benefits from vendoring.
- Operational Maturity: Mature CI/CD enables safer convergent patterns.
Quick Comparison
| Strategy | Convergence | Overhead | Best For |
|---|---|---|---|
| Continuous Version Deployment | Very High | Low | Most teams |
| Folder-Based Versioning | High | Low | Breaking changes |
| Release Tracks/Channels | High | Medium | Many environments |
| Strict Version Pinning | Low | High | Compliance requirements |
| Source-Based Versioning | Low | Low | Simple per-env pinning |
| Git Flow | Medium | Medium | Established Git Flow teams |
Mixing Strategies
You can mix strategies per component:
components/terraform/vpc/ # Trunk-based (all envs converge)eks/ # Trunk-based (all envs converge)monitoring/ # Trunk-based (all envs converge)database/v1/ # Folder-based (prod pinned here)v2/ # Folder-based (dev/staging testing)
Common combinations:
- Tracks for applications, pinning for platform
- Vendoring + tracks for external + internal components
- Folder versioning for breaking changes, continuous for routine updates