SaveMyCert
Log in
5 of 5 free questions left today·for unlimited practice
Deployment

AWS CI/CD Services: CodePipeline, CodeDeploy, and Deployment Strategies

16 min readDVA-C02 · DeploymentUpdated

AWS CI/CD services — CodePipeline, CodeBuild, CodeDeploy, and CodeArtifact — automate the path from a code commit to running software, so releases are repeatable, tested, and reversible. Task 3.4 is the broadest task in the Deployment domain (24% of your scored content), and it produces some of the most recognizable scenario questions on the DVA-C02 exam: which service owns which job, what buildspec.yml and appspec.yml each control, how one API definition serves a different Lambda version per stage, and which deployment strategy fits a stated downtime, risk, or rollback requirement. This lesson walks a full commit-to-production flow, compares all-at-once, rolling, immutable, blue/green, and canary deployments, covers CodeDeploy traffic shifting for Lambda and ECS alongside Elastic Beanstalk deployment policies, and finishes with rollback mechanics and release management using branches, tags, and versioned artifacts.

What you’ll learn
  • Map CodePipeline, CodeBuild, CodeDeploy, and CodeArtifact to their roles in a commit-to-production flow
  • Read buildspec.yml and appspec.yml at exam depth, including the lifecycle hooks for EC2, Lambda, and ECS deployments
  • Promote an API through API Gateway stages and drive per-stage Lambda aliases with stage variables
  • Choose among all-at-once, rolling, immutable, blue/green, and canary strategies for a stated risk and downtime requirement
  • Configure CodeDeploy traffic shifting for Lambda and Elastic Beanstalk deployment policies
  • Design rollbacks triggered by CloudWatch alarms and manage releases with branches, tags, and versioned artifacts

The AWS CI/CD toolchain: who does what

Four services divide the CI/CD work, and the exam repeatedly checks that you know which owns which job:

  • AWS CodePipeline is the orchestrator. A pipeline is a sequence of stages (Source, Build, Test, Deploy — you name them), and each stage runs one or more actions: pulling source, running a CodeBuild project, deploying a CloudFormation stack, invoking a Lambda function, or pausing for a manual approval. An approval action halts the pipeline until someone approves or rejects it (it fails automatically after seven days), which is how a human sign-off sits between staging and production.
  • AWS CodeBuild is the managed build and test runner: it starts a container, executes the commands in buildspec.yml, and emits artifacts. It does the compiling and testing; it does not orchestrate anything.
  • AWS CodeDeploy automates deployments to three compute platforms — EC2/on-premises instances, Lambda functions, and ECS services — following the lifecycle described in appspec.yml and a chosen deployment configuration.
  • AWS CodeArtifact is a managed package repository for formats such as npm, PyPI, Maven, and NuGet. Builds authenticate to it and pull approved dependencies (upstream repositories can proxy public registries), and your own libraries publish there for other builds to consume.

The source stage watches a provider — a Git repository connected through a CodeConnections connection (GitHub, GitLab, Bitbucket), an S3 bucket, or an ECR image — and each stage hands its output artifact to the next through S3. Keep the one-line summary: CodePipeline coordinates, CodeBuild builds and tests, CodeDeploy releases, CodeArtifact feeds dependencies.

CodeBuild and the buildspec.yml

buildspec.yml is the contract between your repository and CodeBuild: a YAML file, by default at the repository root, that declares what to run and what to keep. Its phases run in a fixed order:

  • install — set up runtimes with runtime-versions (for example, a specific Node.js or Python) and install tooling.
  • pre_build — sign in and prepare: authenticate to Amazon ECR before pushing images, or run aws codeartifact login --tool npm so dependency installs resolve from CodeArtifact instead of the public registry.
  • build — compile, run unit tests, build the container image, or run sam build.
  • post_build — finish up: push the image, package templates, stamp version metadata.

The artifacts section lists the files to hand to the next pipeline stage — a packaged CloudFormation template, a zip, an image definitions file — which CodePipeline stores in S3. A reports section can publish test results, and cache speeds up repeat builds.

Configuration comes in through env: plain variables, plus parameter-store and secrets-manager references that resolve at build time so credentials never live in the file. If any phase command exits nonzero, the build fails and the pipeline stops — which is exactly the behavior a test phase exists to provide. For the exam: buildspec belongs to CodeBuild and describes how to build; do not confuse it with appspec, which belongs to CodeDeploy and describes how to deploy.

CodeDeploy: deployment groups and appspec files

CodeDeploy organizes work into an application, one or more deployment groups, and a deployment configuration. The deployment group is the "where and how": which EC2 instances (selected by tags or an Auto Scaling group), which Lambda alias, or which ECS service to target; which deployment configuration to use; which CloudWatch alarms to watch; and whether to roll back automatically. The appspec.yml file travels with the revision, and it looks different on each compute platform — a distinction the exam tests directly:

  • EC2/on-premises: the appspec maps archive files to destinations, sets permissions, and runs hook scripts on the instance through the lifecycle: ApplicationStop, BeforeInstall, AfterInstall, ApplicationStart, then ValidateService. ValidateService is your smoke test — if the script fails, the deployment fails.
  • Lambda: no files are copied. The appspec names the function, the alias, and the current and target versions, and the only hooks are BeforeAllowTraffic and AfterAllowTraffic — each one a separate Lambda function that runs validation and reports success or failure back to CodeDeploy around the traffic shift to the new version.
  • ECS: the appspec points at the new task definition and the container and port to route to, with hooks (BeforeInstall, AfterInstall, AfterAllowTestTraffic, BeforeAllowTraffic, AfterAllowTraffic) implemented as Lambda functions around a blue/green replacement of task sets. AfterAllowTestTraffic runs while the replacement tasks receive traffic only on a test listener — your chance to validate before real users arrive.

Remember the pattern rather than memorizing prose: on instances, hooks are scripts that run on the box; on Lambda and ECS, hooks are Lambda functions that validate a traffic shift. ValidateService exists only on EC2/on-premises.

From commit to production: a walked-through pipeline

Walk one commit through a serverless pipeline, because the exam asks about this flow end to end:

  1. Commit. A developer merges to main. The pipeline's source action, watching the connected repository, downloads the revision and produces the source artifact. Committing code is the trigger; nobody starts deployments by hand.
  2. Build and unit test. A CodeBuild action runs sam build and the unit test suite, then sam package, which uploads the function artifacts to S3 and writes a packaged template — the build artifact.
  3. Deploy to test. A CloudFormation deploy action updates the app-test stack from the packaged template. Because the stack already exists, this is an update of existing IaC — CodePipeline's CloudFormation action can create a change set (CHANGE_SET_REPLACE) and execute it (CHANGE_SET_EXECUTE) as two separate actions.
  4. Integration test. Another CodeBuild action fires stored test events and HTTP calls at the test stack's API and fails the pipeline on any assertion error.
  5. Approval. A manual approval action pauses the run. A reviewer inspects the test results — and, for production, the pending change set, which lists exactly which resources will change or be replaced — then approves.
  6. Deploy to production. The same packaged template updates the app-prod stack, with CodeDeploy shifting Lambda traffic gradually under a canary configuration (covered below).

Notice what makes this safe: the same immutable build artifact moves through every environment; environments differ only by stack name and parameters; humans approve between environments but never build or copy anything by hand. When a question describes "a commit invokes build, test, and deployment actions," it is describing this pipeline.

Lambda packaging, API Gateway stages, and custom domains

Two packaging options exist for Lambda, and the pipeline decides which artifact it produces:

  • .zip archives — the classic package. Small archives upload directly; larger ones are staged in S3 and referenced from there. A .zip package is limited to 50 MB zipped for direct upload and 250 MB unzipped including layers, so heavy dependency trees eventually hit the ceiling.
  • Container images — the function is built as a container image, pushed to Amazon ECR, and referenced by the function. Images can be up to 10 GB, reuse your existing container tooling, and version through ECR tags — with the same immutable-tag discipline as any other image.

Either way, the deploy step is the same idea: update the function code from the new artifact, publish a version, and move an alias — which is exactly what CodeDeploy's Lambda traffic shifting automates.

On the API side, an API Gateway stage is the deployment target: a named pointer (test, prod) to an immutable deployment snapshot of the API. Promoting an API release means creating a deployment and attaching it to the next stage — the definition moves forward while the stage URLs stay stable.

Custom domain names decouple callers from AWS-generated invoke URLs. You attach an ACM certificate to api.example.com and add base path mappings that route path prefixes to an API and stage — /v1 to the prod stage of one API, /beta to another. Callers keep one hostname while you re-map which deployment serves each path, which is itself a release lever: repointing a base path mapping promotes an API without any client changing anything.

Stage variables: one API definition, a different Lambda per stage

Stage variables are per-stage key-value pairs that your API definition can reference anywhere configuration is allowed, written as ${stageVariables.name}. They exist to solve one problem: you want a single API definition, deployed once, whose behavior differs by stage.

The classic exam pattern wires them to Lambda aliases. Define each integration's function as arn:aws:lambda:us-east-1:123456789012:function:orders:${stageVariables.env}. Then set the variable env to dev on the dev stage and prod on the prod stage, and create matching dev and prod aliases on the function. One API definition now invokes the dev-approved function version from the dev stage and the production version from prod — you promote a Lambda release by moving the alias, promote an API release by deploying to the stage, and neither touches the other.

Two supporting details earn points. First, permissions: API Gateway needs resource-based permission to invoke each alias it targets, so grant lambda:InvokeFunction per alias, not just on the bare function — a missing per-alias permission is a classic "works in dev, 500s in prod" distractor. Second, stage variables are configuration, not secrets — they are visible in the console and in logs, so database passwords belong in Secrets Manager, never in stage variables. Beyond alias routing, stage variables can also select an HTTP integration endpoint per stage or feed values into mapping templates, but "same API, different Lambda per stage" is the scenario to recognize on sight.

Deployment strategies compared

Deployment strategies trade speed against risk, rollback time, and cost. The exam states a requirement — zero downtime, limited blast radius, cheapest possible, fastest recovery — and expects you to name the strategy:

StrategySpeedRisk / blast radiusRollbackExtra cost
All at onceFastestEvery instance at once; downtime likelyRedeploy previous version (slow)None
RollingModerateOne batch at a time; reduced capacity during deployRe-roll in batches (slow)None
Rolling with additional batchModerateBatched, but capacity never dropsRe-roll in batches (slow)One extra batch during deploy
ImmutableSlowerNew instances only; old fleet untouchedTerminate the new fleet (fast)Full second fleet during deploy
Blue/greenSlowerNo traffic hits the new version until cutoverShift traffic back (fastest)Two full environments
Canary / linearGradualSmall percentage exposed firstShift the small slice back (fast)Two versions live briefly

Where each runs:

  • Lambda via CodeDeploy: traffic shifts between two versions behind an alias. Predefined configurations name the shape — Canary10Percent5Minutes sends 10% of traffic to the new version, waits five minutes, then shifts the rest; Linear10PercentEvery1Minute adds 10% each minute; AllAtOnce flips immediately. BeforeAllowTraffic and AfterAllowTraffic hooks validate around the shift.
  • ECS via CodeDeploy: blue/green — a replacement task set starts alongside the original, optionally receives test-listener traffic, then the load balancer shifts production traffic.
  • Elastic Beanstalk: deployment policies all at once, rolling, rolling with additional batch, immutable, and traffic splitting (a canary between instance fleets); classic blue/green is two Beanstalk environments plus a CNAME swap.

Match the trigger words: "zero downtime" means blue/green or immutable, "shift 10% of traffic first" means canary, "cheapest and downtime is acceptable" means all at once.

Rollbacks, labels, and release management

Rollback questions test whether you know each mechanism's trigger and speed:

  • Automatic rollback on alarms. A CodeDeploy deployment group can attach CloudWatch alarms and enable auto-rollback: if the deployment fails or an alarm fires during it, CodeDeploy redeploys the last known good revision without a human touching anything. For Lambda canary deployments this is the flagship pattern — an alarm on the new version's errors during the bake window aborts the shift and returns the alias to the old version, so most users never saw the failure. Alarm design itself is Domain 4 material; here the alarm is simply the rollback trigger.
  • CloudFormation rollback. A failed stack update automatically rolls back to the previous working state; the pipeline's deploy action then reports failure while the environment stays healthy.
  • Redeploying a previous version. The universal fallback — run the deploy stage again with the prior artifact, or in Elastic Beanstalk deploy an earlier application version. Reliable, but slowest, because you sit through a full deployment.
  • Blue/green rollback is fastest because nothing needs rebuilding or redeploying: the old environment is still running, so recovery is just shifting traffic back to it.

Release management supplies the "previous version" you return to. Branches separate work in flight from what ships: the pipeline watches a release branch, so merging is releasing. Git tags label the exact commit each release came from, and artifacts carry matching immutable versions — a versioned package in CodeArtifact, a uniquely tagged image in ECR, a numbered Lambda version. When production breaks, that discipline is what makes "roll back to yesterday's release" a five-minute action instead of an archaeology project.

Tip. Task 3.4 questions map stated requirements to strategies and services: "zero downtime" points to blue/green or immutable, "shift 10% of traffic and watch alarms" to a CodeDeploy canary configuration, "different Lambda function per stage" to stage variables referencing aliases, and "preview production changes before applying" to a change set plus a manual approval action. Expect appspec hook lists matched to the correct compute platform and buildspec-versus-appspec ownership questions. When rollback speed is the requirement, blue/green wins because traffic simply shifts back to the still-running old environment.

Key takeaways
  • CodePipeline orchestrates; CodeBuild builds and tests; CodeDeploy deploys; CodeArtifact hosts packages.
  • buildspec.yml drives CodeBuild (install, pre_build, build, post_build); appspec.yml drives CodeDeploy.
  • Lambda and ECS appspec hooks are Lambda functions validating a traffic shift; ValidateService exists only for EC2/on-premises.
  • "Different Lambda per stage" means API Gateway stage variables referencing a Lambda alias in the integration ARN.
  • "Zero downtime" points to blue/green or immutable; "shift 10% of traffic" points to canary.
  • Canary10Percent5Minutes shifts 10% of traffic to the new version, waits five minutes, then shifts the rest.
  • Blue/green rollback is fastest because the old environment is still running — recovery is just shifting traffic back.
  • CodeDeploy rolls back automatically when the deployment fails or an attached CloudWatch alarm fires.

Frequently asked questions

What is the difference between CodePipeline, CodeBuild, and CodeDeploy?

CodePipeline is the orchestrator: it models the release as stages of actions and moves artifacts between them. CodeBuild executes the build and test commands defined in buildspec.yml inside a managed container. CodeDeploy performs the deployment itself to EC2/on-premises, Lambda, or ECS, following appspec.yml and a deployment configuration. A typical pipeline uses all three: CodePipeline calls CodeBuild to build, then CodeDeploy to release.

What does Canary10Percent5Minutes mean in CodeDeploy?

It is a predefined Lambda deployment configuration: CodeDeploy shifts 10% of the alias's traffic to the new function version, waits five minutes while alarms and hooks can catch problems, then shifts the remaining 90%. If an attached CloudWatch alarm fires during the wait, CodeDeploy rolls traffic back to the original version automatically.

How do API Gateway stage variables work with Lambda aliases?

You reference a stage variable inside the integration's function ARN, for example function:orders:${stageVariables.env}, and set env to a different value on each stage — dev on the dev stage, prod on the prod stage. Each value matches a Lambda alias, so every stage invokes its own approved function version from one shared API definition. API Gateway also needs invoke permission granted per alias.

Which deployment strategy has the fastest rollback?

Blue/green. The previous environment keeps running at full capacity while the new one takes traffic, so rolling back is just shifting traffic back to the old environment — no rebuild, no redeploy. Immutable deployments are close behind because rollback only terminates the new fleet, while all-at-once and rolling are slowest since they require redeploying the previous version.

What are the appspec.yml hooks for a Lambda deployment?

Only two: BeforeAllowTraffic and AfterAllowTraffic. Each names a separate Lambda function that CodeDeploy invokes to validate the deployment before and after traffic shifts to the new version; the hook function must report success or failure back to CodeDeploy. There is no file copying and no ValidateService hook — those belong to EC2/on-premises deployments.

Which Elastic Beanstalk deployment policy avoids reduced capacity during a deploy?

Rolling with additional batch launches one extra batch of instances first, so full capacity is maintained while batches update, at the cost of paying for the extra batch during the deployment. Immutable goes further: it builds an entirely new set of instances and swaps them in, keeping full capacity and giving a fast rollback, but doubles instance cost for the duration of the deploy.

Test yourself on this topic
Practice questions with full explanations.
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.