Folder-Based Versioning
Folder-Based Versioning is the foundational folder organization approach within Continuous Version Deployment. Components are organized in simple, explicit folders (vpc/, eks/, rds/) on the main branch. What you see is what you get —no magic, no hidden versioning. This straightforward structure makes divergence visible and patching any version straightforward.
This is the recommended starting point for most teams and what most components use. The explicit folder structure provides clarity: you can see at a glance which components exist and how they're organized. All subsequent folder organization approaches (Release Tracks/Channels and Strict Version Pinning) build on this foundation.
You will learn
- No magic: what you see in the folder structure is what you get
- Explicit divergence visibility through folder organization
- Straightforward patching—modify the component folder directly
- Foundation that other folder organization approaches build upon
- Clear separation between different components
Use Cases
Use the Folder-Based Versioning pattern when:
- You need significant component rework that will take time to stabilize
- You want explicit version boundaries visible in the repository
- You need to run multiple versions side-by-side for extended periods
- You're making breaking changes that require careful migration
- You want clear separation between stable and experimental code
- You need gradual migration paths for complex components
Problem
Major component changes often require extended development periods and careful migration strategies. Traditional versioning approaches can create challenges:
- In-place changes destabilize existing deployments
- Feature flags add complexity and technical debt
- Branch-based development delays integration and feedback
- Hidden versioning makes it hard to understand what's deployed where
Folder-Based Versioning addresses these issues by making versions first-class citizens in the repository structure.
Solution
Create separate folders for each major version of a component. Environments explicitly reference the folder containing their desired version, making version selection transparent and reversible.
Core Principles
- Versions as Folders: Each major version gets its own directory
- Explicit References: Stacks explicitly choose which folder/version to use
- Parallel Development: Multiple versions can evolve independently
- Stable State Keys: Workspace keys remain constant across version switches
- Clear Deprecation: Old versions are clearly marked and eventually removed
Implementation
Directory Structure
Organize components with version-specific folders:
Directory Structure
Stack Configuration
Environments reference specific version folders:
- Development
- Production
stacks/dev/us-east-1.yaml
stacks/prod/us-east-1.yaml
Version Naming Conventions
Choose clear, consistent naming patterns within your component folders:
components/terraform directory structure
Workspace Key Management
This pattern works best with Atmos auto-generated backend configuration. The workspace_key_prefix must remain stable across version changes to prevent state conflicts:
# WRONG - Version in workspace key causes state problems
settings:
workspace_key_prefix: "prod/vpc/v2" # Don't do this!
# CORRECT - Stable workspace key across versions
settings:
workspace_key_prefix: "prod/vpc" # Version-agnostic key
When the workspace key includes version information, switching versions requires complex state migrations. Keep it stable!
Migration Strategies
Gradual Migration
Roll out new versions progressively through environments:
migration-plan.yaml
In-Place Upgrade
For backwards-compatible changes, switch the folder reference:
# Before upgrade - verify current state
atmos terraform plan vpc --stack prod-us-east-1
# Update stack configuration to point to new version
# Edit: metadata.component from "vpc/v1" to "vpc/v2"
# Plan with new version - should show intended changes
atmos terraform plan vpc --stack prod-us-east-1
# Apply the upgrade
atmos terraform apply vpc --stack prod-us-east-1
Rollback Strategy
Folder-based versioning makes rollback trivial - just switch the folder reference:
Update Stack Configuration
# stacks/prod/us-east-1.yaml
components:
terraform:
vpc:
metadata:
# Rollback from v2 to v1
component: vpc/v1 # Was: vpc/v2
settings:
workspace_key_prefix: "prod/vpc" # Keep stable!
Validate and Apply
# Validate the rollback
atmos terraform plan vpc --stack prod-us-east-1
# Review the changes - should show reverting to v1 behavior
# Apply the rollback
atmos terraform apply vpc --stack prod-us-east-1
Since the old version folder still exists unchanged, rollback is instantaneous and risk-free. The stable workspace key means no state migration is needed.
Rollback Verification
# Quick sanity check - verify stack config points to correct folder
atmos describe component vpc --stack prod-us-east-1 | grep "component:"
# Should show: component: vpc/v1
# TRUE VERIFICATION - plan should show no changes
atmos terraform plan vpc --stack prod-us-east-1
# Should output: No changes. Your infrastructure matches the configuration.
The "no changes" output proves that the rollback was successfully applied to the infrastructure, not just the configuration.
Benefits
The Folder-Based Versioning approach provides:
- No Magic: What you see in the folder structure is exactly what you get—no hidden versioning mechanisms or complex abstractions
- Explicit Divergence: When components diverge (e.g., creating
vpc/v2alongsidevpc/), it's immediately visible in the repository structure - Straightforward Patching: Need to patch a component? Modify the folder directly. No need to track down version references or update manifests
- Foundation for Extensions: Provides the base that Release Tracks and Strict Version Pinning build upon
- Clear Organization: Component structure is self-documenting through the folder hierarchy
- Safe Experimentation: New versions can be developed in separate folders without affecting existing deployments
- Gradual Migration: Environments can switch folders at their own pace
Drawbacks
The pattern also has limitations:
- Repository Growth: Multiple versions increase repository size
- Maintenance Overhead: Bug fixes may need to be applied to multiple versions
- Potential Confusion: Developers must understand which version to modify
- Code Duplication: Similar code exists in multiple folders
- Cleanup Discipline: Deprecated versions must be actively removed
Best Practices
-
Version Lifecycle Management: Define clear lifecycle stages for component versions including Preview (experimental, API unstable), Beta (feature complete, testing in progress), Stable (production ready), Deprecated (marked for removal), and Archived (no longer maintained). Document transition criteria and timelines between stages.
docs/version-lifecycle.md
-
Version Documentation: Maintain clear documentation for each version including a component version matrix showing status (Stable, Beta, Preview, Deprecated) and version-specific notes with deprecation dates and migration guidance.
-
Shared Code Management: Minimize duplication by using shared modules that can be imported by multiple versions, reducing maintenance burden while allowing version-specific variations.
-
Testing Strategy: Test all active versions using Atmos validation commands to ensure each version continues to function correctly as the codebase evolves.
-
Migration Process: Migrate components to new versions by updating stack configuration to reference the new version folder, then preview and apply changes using Atmos terraform commands.
Drawbacks and Trade-offs
While Folder-Based Versioning provides clear benefits, consider these trade-offs:
Code Duplication
Multiple copies of similar code exist across version folders with considerable overlap, requiring updates in multiple locations when applying security patches or bug fixes to older versions still in use.
Divergence Risk
When versions evolve independently over extended periods, environments can drift significantly from each other, making it difficult to reason about the overall system state and increasing the likelihood of environment-specific issues.
Release Tracking Challenge
Git commits record when code changes were merged, not when they were deployed to environments. Without additional tooling or documentation, it's challenging to determine which version of a component is actually running in which environment at any given time. Git shows the history of the code, not the deployment state.
Summary
Folder-Based Versioning provides explicit, visible version management through repository structure. It excels when you need to maintain multiple versions in parallel, make breaking changes safely, or provide clear migration paths. While it can increase repository size and maintenance overhead, the clarity and safety it provides often outweigh these costs, especially for critical infrastructure components.
Folder-based versioning makes version boundaries explicit and migrations reversible. It's ideal for major version changes that require extended development and careful rollout strategies.
Related Patterns
- Versioning Schemes - Simple naming and sequential versioning work well with folder-based approach
- Release Tracks/Channels - Abstract version management through tracks
- Vendoring Components - Local copies with origin tracking
- Strict Version Pinning - Explicit version control per environment
- Component Catalog - Organizing reusable components