Filter concepts by levelShowing all levels.

AWS · CI/CD

CI/CD on AWS

Pipeline stages and artifacts, the AWS services and their alternatives, deployment strategies, and migrations

  • Build once, promote by digesta tag is a mutable pointer
  • Rollback is a configured pathnot a fix written mid-incident
  • Rolling and canary run two versionsso the change must be backward compatible
  • Code rolls back; data does notexpand, dual-write, switch, contract

1.Pipeline Stages, Artifacts, and Rollback

A pipeline describes how a code change reaches production. It is a series of stages — source, build, test, deploy — and each stage contains actions that operate on artifacts: the source tree, the built package, the deployment definition. The build stage produces an artifact once, and every later stage deploys that same artifact rather than rebuilding it.

Key features

  • A pipeline is a workflow made of stages; a stage isolates an environment and limits how many concurrent changes reach it
  • Valid CodePipeline action types are `source`, `build`, `test`, `deploy`, `approval`, and `invoke`, and actions in a stage can run in series or in parallel
  • Artifacts are produced by some actions and consumed by others — input artifacts and output artifacts — and are passed between actions through the pipeline artifact bucket
  • A stage is locked while it processes an execution, so two executions cannot occupy the same stage at once
  • In the default SUPERSEDED execution mode a newer execution replaces an older one waiting to enter a locked stage; PARALLEL and QUEUED modes behave differently
  • A failed stage can be retried or rolled back to a specified previous successful execution — automatically, if configured — and an approval action is the human gate that makes "production requires a person" a pipeline property rather than a convention

What belongs in each stage

What belongs in each stage
StageProducesFails when
SourceThe source revision (commit or object version)The trigger filter does not match, or credentials expired
BuildThe immutable artifact — image digest, zip, templateCompilation, dependency resolution, or a lint gate fails
TestA pass/fail verdict on that artifactA test fails, or coverage/security gates are not met
Deploy (staging)A running environment on that artifactHealth checks fail, or a migration errors
ApprovalA recorded human decisionIt times out, or someone rejects it
Deploy (production)The same artifact, liveHealth checks fail — which should trigger rollback
One artifact, many stages
triggersoutputartifactsameartifactgatepromote

Source

commit or tag triggers the pipeline

Build

produces the artifact — once

Test

against that artifact

Deploy staging

same artifact

Approval

human gate

Deploy production

same artifact again

  • Source — commit or tag triggers the pipeline
    • leads to Build (triggers)
  • Build — produces the artifact — once
    • leads to Test (output artifact)
  • Test — against that artifact
    • leads to Deploy staging (same artifact)
  • Deploy staging — same artifact
    • leads to Approval (gate)
  • Approval — human gate
    • leads to Deploy production (promote)
  • Deploy production — same artifact again

Signature

pipeline ⊃ stages ⊃ actions (source | build | test | deploy | approval | invoke) · artifacts flow between them

Source → build → test → deploy → approval → deploy, with one artifact flowing through all of it. Build once, promote by digest, and make rollback a configured path rather than a forward fix written during an incident.

2.CodeBuild, CodePipeline, CodeDeploy — and the Alternatives

AWS splits CI/CD into three services. CodeBuild runs build and test commands in a managed container. CodePipeline is the orchestration — the stages, the artifact hand-offs, the approvals. CodeDeploy handles the deployment itself, including blue/green traffic shifting on Lambda and ECS. GitHub Actions and GitLab CI cover the first two and often hand deployment to CodeDeploy or to the AWS CLI.

Key features

  • CodeDeploy automates deployments to EC2/on-premises instances, Lambda functions, and ECS services — three compute platforms with different behaviour
  • All Lambda and ECS deployments through CodeDeploy are blue/green; only EC2/on-premises can do an in-place deployment
  • For ECS, CodeDeploy installs the new version as a replacement task set, reroutes production traffic to it, and terminates the original task set after success
  • CodeBuild runs your build in a managed container and can reach private subnets when configured with a VPC, which is what a self-hosted runner is usually needed for elsewhere
  • GitHub Actions and GitLab CI authenticate to AWS best through OIDC federation into an IAM role — no long-lived access keys stored as repository secrets
  • A common and reasonable split is to build and test where the code lives, and deploy with CodeDeploy or CloudFormation for the traffic shifting and rollback behaviour

Who does what

Who does what
JobAWS serviceCommon alternative
Run build and test commandsCodeBuildGitHub Actions runner, GitLab CI runner
Orchestrate stages and approvalsCodePipelineWorkflow file with environments and required reviewers
Shift traffic and roll backCodeDeployRarely replaced — this is the piece worth keeping
Provision infrastructureCloudFormation / CDK / TerraformThe same tools, invoked from any runner
Store built imagesECRAny registry, but ECR keeps IAM as the auth model

Command

text
# The three CodeDeploy compute platforms, and what a deployment means on each
EC2/On-Premises -> in-place rolling update, or blue/green with new instances
AWS Lambda      -> shift traffic between two versions of the same function
Amazon ECS      -> shift traffic from the original task set to a replacement

CodeBuild = run it, CodePipeline = orchestrate it, CodeDeploy = shift traffic and roll back. Building and testing in GitHub Actions or GitLab CI while deploying with CodeDeploy or CloudFormation is a normal, defensible split — as long as the CI system authenticates via OIDC rather than stored keys.

3.Rolling, Blue/Green, Canary, Immutable, Feature-Flagged

Every deployment strategy is a different answer to one question: while the new version is going out, what is serving traffic? Rolling replaces instances in batches, so both versions run at once. Blue/green stands the new version up beside the old and switches traffic. Canary sends a small slice of traffic first. Immutable replaces rather than updates. Feature flags separate deploying the code from turning the behaviour on.

Key features

  • In-place (rolling) deployment stops the application on each instance, installs the new revision, and restarts it — only the EC2/on-premises platform supports this
  • Blue/green installs the new version on a replacement environment, then reroutes traffic, and AWS notes rollback is faster because traffic can be routed back as long as the original instances still exist
  • All Lambda and ECS CodeDeploy deployments are blue/green; the traffic-shifting configuration is canary, linear, or all-at-once
  • Canary shifts a small percentage first, waits, then shifts the rest; linear shifts equal increments at a fixed interval; all-at-once shifts everything immediately
  • Immutable means never modifying a running instance — the new version is a new instance from a new image, which is what makes rollback a matter of pointing back at the old one
  • A feature flag decouples deploy from release — the code ships dark and can be turned off without a deployment — while rolling and canary both mean two versions serve traffic at once, so the change must be backward compatible with the version it replaces

Choosing a strategy

Choosing a strategy
StrategyProtects againstCosts
Rolling (in-place)Total outage during deployBoth versions live; slow rollback
Blue/greenA bad version reaching users at allDouble capacity during the switch
CanaryA failure that only shows under real trafficLonger deploys; needs good metrics to judge the canary
LinearSudden full exposureLongest deploy window of the three
ImmutableDrift and half-updated hostsA new image per release
Feature flagA behaviour change, independent of the deployFlag lifecycle management; dead flags accumulate
Two versions at once, or not

Rolling / canary — both versions live

  • Cheapest in capacity: no second environment
  • Requires backward-compatible changes
  • Rollback means another rolling pass
  • Canary limits exposure by traffic share

Blue/green — one version serves

  • Needs capacity for two environments briefly
  • Test the replacement before any traffic reaches it
  • Rollback is rerouting traffic back
  • The original can be kept running for a bake period
  • Rolling / canary — both versions live
    • Cheapest in capacity: no second environment
    • Requires backward-compatible changes
    • Rollback means another rolling pass
    • Canary limits exposure by traffic share
  • Blue/green — one version serves
    • Needs capacity for two environments briefly
    • Test the replacement before any traffic reaches it
    • Rollback is rerouting traffic back
    • The original can be kept running for a bake period

Signature

rolling | blue/green | canary | linear | all-at-once | immutable | feature-flagged

Rolling and canary run two versions at once, so the change must be backward compatible. Blue/green guarantees one version serves and makes rollback a reroute. Canary needs an alarm judging it. Immutable replaces rather than updates. Feature flags separate deploy from release — and must be removed.

4.Database Migrations as Part of the Deployment

Application code can be rolled back. A migration that dropped a column cannot. That asymmetry is why schema changes have to be designed alongside the deployment strategy rather than bolted onto it: during any rolling or canary deployment, the old and new code both talk to one schema, so the schema has to satisfy both at once.

Key features

  • During a rolling or canary deployment, two application versions share one database, so the schema must be compatible with both simultaneously
  • Expand/contract: expand the schema (add, never remove), deploy code that writes both shapes, backfill, deploy code that reads the new shape, then contract in a later release
  • A rename is the classic trap — it is a drop plus an add to every running instance of the old version
  • Migrations run once per deployment, not once per task, so they belong in a separate pipeline step rather than in application startup
  • A long-running migration holding a lock can block the application it is deployed alongside, turning a deploy into an outage
  • The rollback plan for a migration is a separate question from the rollback plan for the code — and a blue/green deployment only removes the two-versions constraint when each version has its own data, not when both share one database

Migration shapes and their deployment risk

Migration shapes and their deployment risk
ChangeSafe during a rolling deploy?Handling
Add a nullable columnYesOld code ignores it
Add a column with a defaultUsuallyCheck the engine's rewrite behaviour on a large table
Add an indexYes, if built concurrentlyA blocking index build locks writes
Rename a columnNoExpand/contract: add, dual-write, switch, drop
Drop a columnNoOnly after no deployed version references it
Narrow a type or add NOT NULLNoBackfill first, constrain in a later release
Expand/contract across three releases

Release 1 — expand

Add the new nullable column. Old code ignores it; nothing breaks.

Release 2 — dual write

New code writes both columns and still reads the old one. Backfill in the background.

Release 3 — switch reads

New code reads the new column. The old column is now unused but still present.

Release 4 — contract

Drop the old column, once no deployed version references it.

  1. Release 1 — expand — Add the new nullable column. Old code ignores it; nothing breaks.
  2. Release 2 — dual write — New code writes both columns and still reads the old one. Backfill in the background.
  3. Release 3 — switch reads — New code reads the new column. The old column is now unused but still present.
  4. Release 4 — contract — Drop the old column, once no deployed version references it.

Signature

expand → dual-write + backfill → switch reads → contract · migrations as a pipeline step, not on startup

Two versions share one database during any rolling or canary deploy, so every schema state must satisfy both. Expand (additive), dual-write, switch reads, contract — across separate releases. Run migrations as their own pipeline step, and never ship an irreversible migration alongside the code that needs it.

Remember

  • A stage is locked while it processes one execution; the default SUPERSEDED mode lets a newer execution replace a waiting one.
  • All Lambda and ECS CodeDeploy deployments are blue/green — only EC2/on-premises can deploy in place.
  • A canary without an alarm judging it is only a slower way to ship a bad version.
  • Run migrations as their own pipeline step; on container startup they race every task and every scale-out.

Pro tip

  • External CI (GitHub Actions, GitLab CI) should assume an IAM role via OIDC — a stored access key is a bearer credential with no expiry.
  • Blue/green is not merely the safer option for a non-backward-compatible change; it is the only one that works, because it guarantees a single version serves traffic.

Next up

  • ECR and Container Supply Chain
  • ECS Deployment Architecture
  • Infrastructure as Code

Sources

  • CodePipeline concepts — docs.aws.amazon.com/codepipeline/latest/userguide/concepts.html
  • What is CodeDeploy? — docs.aws.amazon.com/codedeploy/latest/userguide/welcome.html
  • Checked against official AWS documentation 2026-08-29

Spotted a mistake on this page? Tell us.