Continuous Version Deployment
Continuous Version Deployment is the recommended trunk-based deployment strategy where environments progressively converge to whatever component path they reference in stack configurations. All environments work from the main branch trunk, with automated testing and deployment pipelines controlling progressive rollout. This strategy decouples release from deployment using automation rather than version control strategies, promoting automated convergence while maintaining safety through comprehensive testing.
This strategy represents the sweet spot for most organizations—simple enough to understand and operate, yet powerful enough to handle complex deployment scenarios. By deploying all environments from the same trunk and using automation to control the rollout, teams can move fast with confidence while maintaining visibility into change impacts across their entire infrastructure.
Within this strategy, you can organize your components using different folder structures depending on your needs: simple Folder-Based Versioning, Release Tracks/Channels, or Strict Version Pinning.
This deployment strategy supports multiple folder organization approaches. Most components use simple folder-based versioning, while specific components requiring planned divergence can use release tracks or strict version pinning. See the Planned Divergence section for detailed examples of combining approaches.
You will learn
- All environments deploy commits from the main branch trunk (trunk-based development)
- Environments converge to the same commit through automated progressive rollout
- Controlled, time-bound divergence during deployment pipeline execution
- Changes are immediately visible across all environments during planning
- Automation drives convergence, reducing operational overhead and drift
Strategy Overview
Continuous Version Deployment is the overarching trunk-based deployment strategy where environments progressively converge to whatever component path they reference in their stack configurations. The key principle: whatever component folder your stack references, your environment will converge to that version through automated progressive rollout.
Instead of managing different versions per environment through Git branching, you use:
- Automated testing pipelines to validate changes before they reach production
- Progressive deployment strategies to roll out commits incrementally across environments
- Environment-specific configuration to control behavior per environment
- CI/CD automation to orchestrate the convergence process
This approach aligns with modern DevOps practices and trunk-based development, where the main branch is always deployable and releases are controlled through automation. Environments naturally diverge during the rollout window (while the pipeline executes), then automatically converge once the deployment completes.
Folder Organization Approaches
Within this deployment strategy, you can organize your component folders in different ways depending on your needs:
Folder-Based Versioning - The foundational approach with simple folders (vpc/, eks/, rds/). All environments typically reference the same component folder and converge to it. This is the recommended starting point and what most teams use for most components.
Release Tracks/Channels - Organizes components into named channels (alpha/vpc, beta/vpc, prod/vpc). Environments subscribe to tracks and converge to whatever version is in their track.
Strict Version Pinning - Uses explicit SemVer versions (vpc/1.2.3, vpc/2.0.0). Works well when vendoring from external sources or managing shared component libraries.
All these approaches share the same deployment philosophy: environments converge to the component path they reference through progressive automated rollout.
These folder organization approaches work seamlessly with Vendoring Component Versions. Vendoring components locally provides visibility, searchability, and operational control. Atmos also supports just-in-time source provisioning when you prefer remote version references. See the Component Sourcing Philosophy for the tradeoffs.
How It Works
Basic Structure
All your stack configurations reference the same components without version qualifiers:
- Development
- Staging
- Production
Deployment Pipeline
The key to this pattern is a robust deployment pipeline that validates changes progressively. Your CI/CD system orchestrates the convergence process:
Validation Stage (on pull request):
- Run
terraform validateand security scans (tfsec, checkov, etc.) - Execute policy checks (OPA, Sentinel)
- Generate and display terraform plans for all environments
- Provide visibility into what will change across dev, staging, and production
Progressive Deployment (after merge to main):
- Dev deployment: Automatically deploy to development environment
- Dev validation: Run smoke tests and basic functionality checks
- Staging deployment: Deploy to staging after dev validation passes
- Staging validation: Execute comprehensive integration and performance tests
- Production approval: Require manual approval or wait for time-based gate
- Production deployment: Deploy to production with monitoring
- Production validation: Post-deployment health checks and alerting
Monitoring & Rollback:
- Track deployment metrics and error rates
- Configure automated alerts for anomalies
- Maintain rollback procedures (revert commit + re-run pipeline)
Decoupling Release from Deployment
A core principle of this pattern is separating deployment (putting code in an environment) from release (making changes available to users). The industry has established that this decoupling increases speed and stability.
Decoupling deploy from release increases speed and stability when delivering software.
More-frequent deployments reduce the risk associated with change, while business stakeholders retain control over when features are released to end users.
While application teams often achieve this through runtime feature flags (LaunchDarkly, Thoughtworks Feature Toggles), infrastructure-as-code benefits from a different approach:
Atmos decouples through progressive deployment automation - where CI/CD gates control when environments receive changes, and comprehensive plan previews enable informed release decisions.
How Atmos Achieves Decoupling
Deployment: Merge to main declares intent to deploy everywhere
Release: CI/CD gates control WHEN each environment actually gets the changes
Preview: See the impact on ALL environments before releasing to ANY
Atmos's Key Advantage: Unlike approaches requiring version pinning updates, you see the plan for every environment immediately after merge—dev, staging, AND production—without touching any configuration. This visibility enables informed decisions about release timing.
Knowing that deploying new code will not automatically trigger a release provides that safety net.
This decoupling is achieved through two separation mechanisms:
-
Environmental Configuration Separation: Stack configurations (stacks/dev/, stacks/staging/, stacks/prod/) provide environment-specific variables and settings, allowing the same component to behave differently per environment.
-
Component Version Separation: The
metadata.componentpath determines which component implementation to use, enabling environments to reference different versions through folder organization.
The primary mechanism controlling when deployments are released to each environment is CI/CD approval gates (GitHub Actions, GitLab CI, etc.). These gates control the progression of deployments across environments through automated testing, manual approvals, and time-based holds—more natural for infrastructure than runtime flags while achieving the same goal.
| Approach | Mechanism | Decoupling Method | Best For |
|---|---|---|---|
| Feature Flags (LaunchDarkly) | Runtime switches | Control feature visibility in deployed code | Application features with gradual rollout needs |
| Atmos | CI/CD gates + automation | Control deployment timing across environments | Infrastructure changes with progressive validation |
Environment-specific configuration (Terraform variables, Helm values) provides the most natural way to control infrastructure behavior per environment. While runtime feature flags can supplement this, they add complexity in infrastructure-as-code compared to application development, so they're best reserved for specific use cases rather than general practice.