CD & Deployment Strategies#

Continuous Delivery (CD) ensures that code is always in a deployable state. Continuous Deployment takes this further by automatically releasing every change that passes the pipeline. The deployment strategy you choose determines how risk is managed during releases.


Continuous Delivery vs Continuous Deployment#

AspectContinuous DeliveryContinuous Deployment
DefinitionEvery commit can be deployed to productionEvery commit is deployed to production
Human gateManual approval before prod deployNo manual gate — fully automated
PrerequisiteComprehensive automated testingExtreme confidence in test suite + monitoring
RollbackManual or semi-automatedAutomated rollback on failure
AdoptionWidespreadMostly tech-forward companies
graph LR
    A[Commit] --> B[Build & Test]
    B --> C[Deploy to Staging]
    C --> D{Manual Approval?}
    D -->|Continuous Delivery| E[Deploy to Prod]
    D -->|Continuous Deployment| E
    
    style D fill:#fff3cd

Deployment Strategies#

Blue-Green Deployment#

Maintain two identical production environments. Route traffic entirely to one (blue) while deploying to the other (green). Switch when ready.

graph TD
    LB[Load Balancer]
    LB -->|100% traffic| Blue[Blue Environment v1.2]
    LB -.->|0% traffic| Green[Green Environment v1.3]
    
    style Blue fill:#e3f2fd
    style Green fill:#e8f5e1
AspectDetail
How it worksDeploy v1.3 to Green. Test. Switch LB to Green. Blue becomes standby.
RollbackInstant — switch LB back to Blue
RiskVery low — full testing before any user sees new version
CostHigh — double infrastructure during deployment
DatabaseMust handle schema compatibility between versions
Best forMission-critical systems where downtime is unacceptable

Canary Deployment#

Route a small percentage of traffic to the new version. Gradually increase if metrics are healthy.

graph TD
    LB[Load Balancer]
    LB -->|95% traffic| V1[v1.2 - Stable]
    LB -->|5% traffic| V2[v1.3 - Canary]
    
    style V1 fill:#e3f2fd
    style V2 fill:#fff3cd
PhaseTraffic SplitDurationGate
15% canary15 minError rate < 0.1%
225% canary30 minLatency P99 < 200ms
350% canary1 hourBusiness metrics stable
4100% canary—Full rollout
AspectDetail
RollbackFast — route 100% back to stable
RiskLow — limited blast radius during ramp-up
ObservabilityCritical — need per-version metrics
Best forHigh-traffic services where you can detect issues with small samples

Rolling Deployment#

Replace instances of the old version with the new version one at a time (or in batches).

graph TD
    subgraph "Rolling Update (4 instances)"
        A["Instance 1: v1.3 ✓"]
        B["Instance 2: v1.3 ✓"]
        C["Instance 3: v1.2 → v1.3"]
        D["Instance 4: v1.2"]
    end
    
    style A fill:#e8f5e1
    style B fill:#e8f5e1
    style C fill:#fff3cd
    style D fill:#e3f2fd
AspectDetail
How it worksDrain traffic from one instance, update it, health check, move to next
RollbackModerate — roll forward to previous version or stop mid-roll
RiskMedium — both versions serve traffic simultaneously during rollout
CostLow — no extra infrastructure needed
Best forStateless services with good health checks

Recreate (Big Bang)#

Stop all old instances, deploy new ones. Simple but causes downtime.

AspectDetail
RollbackRe-deploy previous version (downtime again)
RiskHigh — all users affected during transition
CostLowest — no overlap
Best forDev/test environments, batch jobs, systems that can’t run two versions

Strategy Comparison#

StrategyZero DowntimeRollback SpeedCostComplexityTraffic Control
Blue-Green✅InstantHighMediumBinary switch
Canary✅FastMediumHighGranular %
Rolling✅ModerateLowLowPer-instance
Recreate❌SlowLowestLowestNone
Feature Flags✅InstantLowMediumPer-user/segment

Feature Flags#

Feature flags decouple deployment from release. Code is deployed but features are enabled/disabled via configuration:

# Feature flag example
from feature_flags import is_enabled

def get_search_results(query: str, user: User) -> Results:
    if is_enabled("new-search-algorithm", user=user):
        return new_search(query)
    else:
        return legacy_search(query)

Feature Flag Types#

TypePurposeLifetimeExample
ReleaseDark launch new featureDays–weeksNew checkout flow
ExperimentA/B test variantsWeeks–monthsButton colour test
OpsKill switch for featuresPermanentDisable non-critical feature under load
PermissionGate features by user segmentPermanentEnterprise-only feature

Feature Flag Best Practices#

  • Clean up — Remove flags after full rollout (technical debt otherwise)
  • Default safe — Flag off = old behaviour (safe fallback)
  • Monitor — Track metrics per flag state
  • Limit scope — Don’t nest flags or create combinatorial explosion

A/B Testing in Deployments#

A/B testing uses deployment infrastructure to measure business impact:

AspectA/B TestingCanary
GoalMeasure business metrics (conversion, revenue)Validate technical health (errors, latency)
DurationDays–weeks (statistical significance)Minutes–hours
Split criteriaUser segments, random assignmentTraffic percentage
DecisionData-driven (which variant wins)Pass/fail (is it broken?)
RollbackKeep losing variant code (for now)Immediate on failure

Rollback Strategies#

When a deployment goes wrong, you need a fast path back to stability:

StrategySpeedMechanismLimitation
Revert commitMinutesPush revert, re-run pipelineDatabase migrations may not be reversible
Re-deploy previousMinutesDeploy last known good artifactNeed artifact storage with history
Traffic switchSecondsRoute back to blue/previous versionRequires blue-green or similar setup
Feature flag offSecondsToggle flag in configOnly works if feature is flag-gated
Auto-rollbackSecondsAutomated based on metricsRequires well-defined health signals

Automated Rollback Conditions#

# Example: Auto-rollback criteria
rollback:
  triggers:
    - metric: error_rate_5xx
      threshold: "> 1%"
      window: 5m
    - metric: latency_p99
      threshold: "> 2000ms"
      window: 5m
    - metric: health_check
      condition: "3 consecutive failures"
  action: route_traffic_to_previous_version

Database Migrations in CD#

Database changes are the hardest part of continuous deployment because they’re often irreversible:

Expand-Contract Pattern#

graph LR
    A["Step 1: Expand
    Add new column (nullable)"] --> B["Step 2: Migrate
    Code writes to both old & new"] --> C["Step 3: Contract
    Remove old column"]
PrincipleWhy
Backward compatibleNew schema works with old and new code
Forward-onlyNever roll back migrations — always migrate forward
Small batchesOne schema change per deployment
Separate from code deployRun migration, verify, then deploy code that uses it

Deployment Automation#

Environment Promotion#

graph LR
    A[Build Artifact] --> B[Deploy to Dev]
    B --> C[Auto-tests pass]
    C --> D[Deploy to Staging]
    D --> E[Smoke tests + approval]
    E --> F[Deploy to Production]
    F --> G[Post-deploy verification]

Deployment Pipeline Configuration#

# Environment promotion example
deploy-staging:
  stage: deploy
  environment: staging
  script:
    - deploy --env staging --version $CI_COMMIT_SHA
    - run-smoke-tests --env staging
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

deploy-production:
  stage: deploy
  environment: production
  script:
    - deploy --env production --version $CI_COMMIT_SHA
    - run-post-deploy-checks --env production
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual  # Human approval gate
  needs: [deploy-staging]

Progressive Delivery#

Progressive delivery combines deployment strategies with observability:

StageActionDecision
1Deploy to canary (1%)Automated health check
2Expand to 10%Automated metrics check
3Expand to 50%Automated + manual review
4Full rollout (100%)Confidence threshold met

Tools that enable progressive delivery:

  • Argo Rollouts — Kubernetes-native progressive delivery
  • Flagger — Automated canary analysis for Kubernetes
  • AWS CodeDeploy — Canary/linear deployment for ECS and Lambda
  • LaunchDarkly / Unleash — Feature flag management

Key Takeaways#

  • Blue-green gives instant rollback at the cost of double infrastructure
  • Canary provides gradual risk reduction with granular traffic control
  • Rolling is the simplest zero-downtime strategy for stateless services
  • Feature flags decouple deployment from release — deploy anytime, release when ready
  • Automated rollback based on health metrics is the safety net every CD pipeline needs
  • Database migrations require the expand-contract pattern for safe continuous deployment
  • Choose your strategy based on: risk tolerance, infrastructure cost, and observability maturity