AWS CodeDeploy — Getting New Code Onto Live Servers Safely

AWS CodeDeploy — Getting New Code Onto Live Servers Safely

A deep, chapter-by-chapter walkthrough of AWS CodeDeploy — how it is built, how a release actually moves onto running servers and containers, and how to do that without breaking production.

Picture a hospital that needs to replace an old piece of critical equipment with a new one — but the hospital can never fully close, patients keep arriving, and someone has to move the new equipment in, test it, and only then retire the old one, all while care continues uninterrupted. Swapping running software on live servers has that exact same tension: users are actively using the old version right up until the moment the new version takes over, and any mistake in that handoff is felt immediately. AWS CodeDeploy exists to manage that handoff safely and repeatedly, across EC2 instances, on-premises servers, ECS services, and Lambda functions, without anyone having to script the choreography by hand every time. This tutorial goes chapter by chapter through the intermediate-level machinery of AWS CodeDeploy: its architecture, its internal behavior, its failure modes, and the decisions that separate a deployment tool teams trust from one that quietly causes outages.

1Core Concepts, Refreshed

Before going deep into CodeDeploy itself, a few deployment concepts need to be sharp at an intermediate level.

Applications, Deployment Groups, and Revisions

In CodeDeploy, an Application is simply a name that groups related deployment configuration together. A Deployment Group defines exactly which instances, ECS service, or Lambda function a deployment targets, along with rules like how much of the fleet to update at once. A Revision is the actual package of new code and configuration being deployed — for EC2 and on-premises deployments this includes an appspec.yml file describing how to install and start the new version.

In-place vs. Blue/Green Deployments

An in-place deployment stops the application on each instance, installs the new revision, and restarts it, one batch of instances at a time — the same servers are reused throughout. A blue/green deployment instead provisions a completely separate, new set of instances (or a new ECS task set) running the new version, verifies it, and then reroutes traffic to it before terminating the old set entirely.

Simple Analogy

In-place deployment is like renovating a restaurant kitchen room by room while it stays open — some tables might notice the noise. Blue/green deployment is like building an entire new kitchen next door, testing it fully, and then quietly switching all the chefs over to it once it’s ready, before ever touching the old one.

Component

Application

A named container that groups deployment groups and revisions for a given piece of software.

Component

Deployment Group

Defines the target instances or service and the rules governing how a deployment proceeds.

Component

Revision

The specific version of application content and instructions being deployed.

Component

CodeDeploy Agent

Software running on EC2 or on-premises instances that carries out the deployment steps locally.

2Architecture & Components

CodeDeploy’s architecture differs meaningfully depending on which compute platform it’s deploying to.

For EC2 and on-premises deployments, a lightweight CodeDeploy Agent runs on every target instance, polling the CodeDeploy service for new deployment instructions. When a deployment starts, the service tells each targeted instance’s agent to fetch the revision (typically stored in Amazon S3 or a GitHub repository) and execute the lifecycle steps defined in an appspec.yml file. For ECS, there is no agent at all — CodeDeploy instead orchestrates traffic shifting between task sets directly through integration with Elastic Load Balancing. For Lambda, CodeDeploy shifts traffic between function versions using weighted aliases, again with no agent involved.

graph TD
    A[CodeDeploy Service] -->|deployment instructions| B[CodeDeploy Agent on EC2]
    B -->|fetches revision| C[Amazon S3 / GitHub]
    A -->|traffic shifting API calls| D[Elastic Load Balancer]
    D --> E[ECS Task Set - Old Version]
    D --> F[ECS Task Set - New Version]
    A -->|weighted alias update| G[Lambda Function Versions]
        
FIG 1 — CodeDeploy orchestrates differently depending on the target: agent-based for EC2, API-driven traffic shifting for ECS and Lambda

EC2/On-premises Deployments

Uses the CodeDeploy Agent to install and run new code directly on virtual machines or physical servers. Best for traditional server-based applications.

ECS Deployments

Shifts load-balanced traffic between old and new task sets with no agent required. Best for containerized microservices already running on ECS.

Lambda Deployments

Gradually shifts invocation traffic between function versions using weighted aliases. Best for serverless applications needing safe, gradual rollouts.

3Internal Working

A deployment’s internal steps follow a defined lifecycle, whether it targets EC2, ECS, or Lambda.

For an EC2 in-place deployment, the appspec.yml file defines lifecycle event hooks — such as BeforeInstall, Install, AfterInstall, ApplicationStart, and ValidateService — and CodeDeploy runs any scripts you’ve attached to those hooks in a fixed order on each targeted instance. This is what lets you, for example, gracefully deregister an instance from a load balancer before installing new code, and only re-register it once a health check script confirms the new version is actually working.

Simple Analogy

Lifecycle hooks are like a stagehand’s checklist during a theater set change: dim the lights, move the old set off, bring the new set on, check every prop is in place, then raise the lights again — always in the same order, so the audience never sees an unfinished stage.

Deployment configurations control how much of the fleet is updated at once — OneAtATime updates a single instance before moving to the next, HalfAtATime updates half the fleet simultaneously, and AllAtOnce updates everything together. For ECS and Lambda, similar canary and linear configurations control what percentage of traffic shifts to the new version and how quickly the rest follows.

Throughout the deployment, CloudWatch Alarms can be attached to automatically trigger a rollback if error rates or latency spike during the rollout, without waiting for a human to notice and intervene manually.

!
Common Misconception

A deployment reporting “Succeeded” means every lifecycle hook and health check you configured passed — it does not mean the application is bug-free or behaving correctly for every real user scenario, only that the checks you actually wrote were satisfied.

4Data Flow & Lifecycle

A revision’s journey through CodeDeploy follows a predictable sequence from being registered to running live.

1

Revision Registration

New application content and its appspec file are uploaded to S3 or referenced from a GitHub commit.

2

Deployment Creation

A deployment is started against a specific deployment group, targeting a defined set of instances or a service.

3

Lifecycle Execution

Install and validation hooks run in order, or traffic gradually shifts to the new task set or function version.

4

Health Verification

Health checks or CloudWatch Alarms confirm the new version is behaving correctly under real or simulated traffic.

5

Completion or Rollback

The deployment finishes successfully, or automatically rolls back to the last known-good revision if problems are detected.

Deployment history is retained by CodeDeploy, so teams can see exactly which revision was deployed to which environment and when — a detail that matters enormously when diagnosing “which release introduced this bug” weeks after the fact.

Deployment ConfigBehaviorTypical Use Case
OneAtATimeUpdates a single instance, waits, then moves to the nextSmall fleets, cautious rollouts
HalfAtATimeUpdates half the fleet simultaneouslyBalancing speed and safety
AllAtOnceUpdates every instance at the same timeNon-critical or fast-recovery environments
Canary (ECS/Lambda)Shifts a small traffic percentage first, then the restHigh-traffic production services

5Advantages, Disadvantages & Trade-offs

Choosing CodeDeploy over hand-rolled deployment scripts, or over a different deployment tool entirely, involves real trade-offs.

Advantages

  • Consistent deployment behavior across EC2, on-premises, ECS, and Lambda through one service
  • Built-in blue/green and canary strategies without custom scripting
  • Automatic rollback triggered by CloudWatch Alarms during a risky rollout
  • Detailed deployment history and per-instance status for troubleshooting
  • Integrates natively with CodePipeline for full end-to-end delivery workflows

Disadvantages / Trade-offs

  • EC2 deployments require installing and maintaining the CodeDeploy Agent on every instance
  • appspec.yml lifecycle hooks require some upfront scripting investment to get right
  • Less flexible for highly custom, non-standard deployment topologies
  • Debugging a failed lifecycle hook sometimes means digging through per-instance agent logs
“A rollback that works only in theory is not a rollback plan.”

6Performance & Scalability

Deployment speed in CodeDeploy is mostly a function of fleet size, batch configuration, and how much validation work each hook performs.

A OneAtATime configuration is the safest but slowest option for a large fleet, since each instance must fully complete before the next begins; HalfAtATime or a percentage-based configuration trades some safety for significantly faster total deployment time on large fleets. For ECS and Lambda, canary and linear traffic-shifting configurations let you control exactly how gradually traffic moves, balancing rollout speed against blast radius if something goes wrong.

Simple Analogy

Updating one instance at a time is like replacing tires on a car one wheel at a time while slowly driving — very safe, but slow. Updating many at once is like jacking up the whole car and replacing all four tires together — much faster, but the car is more exposed if something goes wrong mid-swap.

Validation scripts attached to lifecycle hooks also affect total deployment time directly — a thorough ValidateService script that runs a full smoke test suite takes longer than one that simply checks whether a process is running, but it also catches more real problems before traffic returns to that instance.

Batch Size
Controls how many instances update at once
Canary %
Controls initial traffic exposure for new versions
Hook Depth
Validation thoroughness trades speed for safety
i
Tip

Start with a conservative deployment configuration for a new application, then move to faster batch sizes only once the team has confidence in the automated health checks catching real problems.

7High Availability & Reliability

CodeDeploy’s core purpose is reliability during change — keeping an application available while its underlying code is actively being replaced.

Blue/green deployments provide the strongest reliability guarantee, since the old environment keeps serving all traffic until the new one is fully verified, and remains available as an instant rollback target for a configurable period after the switch. Automatic rollback, triggered either by a failed deployment lifecycle event or by a CloudWatch Alarm crossing its threshold, removes the dependency on a human noticing a problem quickly enough to react.

sequenceDiagram
    participant CD as CodeDeploy
    participant Old as Old Environment
    participant New as New Environment
    participant Alarm as CloudWatch Alarm
    CD->>New: Deploy new revision
    CD->>New: Run validation hooks
    CD->>Old: Shift traffic to New
    Alarm-->>CD: Error rate spike detected
    CD->>Old: Roll back traffic automatically
        
FIG 2 — An automatic rollback triggered by a CloudWatch Alarm during a blue/green deployment
Practice

Blue/Green by Default

Preferring a fully separate new environment for production-critical applications rather than reusing existing instances.

Practice

CloudWatch-triggered Rollback

Attaching real health alarms to a deployment group so bad releases revert automatically.

Practice

Health Check Hooks

Writing genuinely meaningful ValidateService scripts instead of trivial “process is running” checks.

Practice

Traffic Rerouting Windows

Keeping the old environment available for a defined grace period after cutover, in case a delayed issue surfaces.

8Security

Because CodeDeploy can install new code onto running production systems, its access controls carry real weight.

IAM Roles for the Service and Instances

CodeDeploy needs a service role granting it permission to interact with EC2, ECS, Lambda, and Elastic Load Balancing on your behalf, and EC2 instances running the agent need an instance role permitting them to fetch revisions from S3 or GitHub. Scoping both roles tightly limits what a misconfigured or compromised deployment can actually reach.

Revision Integrity

Since the CodeDeploy Agent fetches revisions from S3 or GitHub, controlling who can write to those source locations is just as important as controlling who can trigger a deployment — an attacker who can plant a malicious revision doesn’t need to touch CodeDeploy’s permissions at all.

Network Access for the Agent

The CodeDeploy Agent needs outbound network access to reach the CodeDeploy service and the revision storage location, which should be scoped through security groups and VPC endpoints rather than granting broad, unrestricted internet access to production instances.

ANTI-PATTERN-01 Avoid
Problem

Allowing any developer with S3 write access to the revision bucket to trigger what is effectively a production code change, without any review process.

Why It’s Harmful

The deployment permission model becomes meaningless if the underlying artifact can be swapped by anyone with bucket access, bypassing every approval gate built into the pipeline.

Correct Approach

Restrict write access to the revision bucket to the pipeline’s own service role, so revisions only ever originate from a reviewed, automated build process.

9Monitoring, Logging & Metrics

Visibility into an in-progress deployment is what makes automatic rollback and confident manual intervention both possible.

CodeDeploy reports per-instance deployment status, so teams can see exactly which instances succeeded, failed, or are still in progress at any moment. The CodeDeploy Agent writes detailed logs locally on each instance, which can be forwarded to CloudWatch Logs for centralized troubleshooting instead of requiring someone to log into individual servers.

Metric

Deployment Success Rate

The percentage of deployments that complete without failure or manual rollback.

Metric

Instances Failed / Skipped

Per-deployment counts showing exactly where a rollout stalled or failed.

Metric

Rollback Frequency

How often deployments trigger an automatic or manual rollback, a strong signal of release quality trends.

Metric

Time to Complete Deployment

Total elapsed time from deployment start to finish, useful for tuning batch size and hook thoroughness.

i
Tip

Review rollback frequency trends over time, not just individual incidents — a rising rollback rate often points to a gap earlier in the pipeline, such as insufficient testing before deployment.

10Deployment & Cloud Integration

CodeDeploy is most often one stage inside a broader continuous delivery workflow rather than a standalone tool.

CodeDeploy plugs directly into AWS CodePipeline as a native Deploy stage action, so a pipeline can build an artifact and hand it to CodeDeploy without any custom integration glue. CloudFormation and CDK can define applications, deployment groups, and their configuration as version-controlled infrastructure, keeping deployment setup consistent and reviewable across environments.

flowchart LR
    A[CodePipeline - Build Stage] --> B[CodeDeploy - Deploy Stage]
    B --> C{Target Platform}
    C --> D[EC2 Auto Scaling Group]
    C --> E[ECS Service]
    C --> F[Lambda Function]
    G[CloudWatch Alarms] -.monitors.-> D
    G -.monitors.-> E
    G -.monitors.-> F
        
FIG 3 — CodeDeploy as the deploy stage of a pipeline, targeting different compute platforms

For EC2 deployments, target instances are usually managed through an Auto Scaling group, so CodeDeploy automatically handles instances that scale in or out during a deployment window, rather than requiring a fixed, manually maintained instance list.

11Design Patterns & Anti-patterns

Certain patterns show up again and again in mature CodeDeploy setups — and so do certain mistakes.

Blue/Green with Alarm-based Rollback

Combining a fully separate new environment with CloudWatch Alarms watching real production metrics, so a bad release both fails safely and reverts automatically without manual intervention.

Meaningful Health Checks in Every Hook

Writing lifecycle hook scripts that actually exercise real application behavior — hitting a health endpoint, checking a database connection — instead of trivially checking that a process started.

Gradual Canary for High-traffic Services

Shifting a small percentage of production traffic first for ECS or Lambda deployments, catching problems while only a fraction of users are affected.

ANTI-PATTERN-02 Avoid
Problem

Writing a ValidateService hook that only checks whether the application process is running, with no check on whether it’s actually serving correct responses.

Why It’s Harmful

A process can be alive and still be completely broken — crash-looping in a way that briefly looks “running,” or serving errors on every request — and a shallow check will happily mark the deployment successful anyway.

Correct Approach

Have validation hooks exercise real application behavior, such as calling a health endpoint that checks downstream dependencies, before declaring an instance healthy.

12Best Practices & Common Mistakes

Most CodeDeploy-related incidents trace back to a handful of recurring, avoidable oversights.

Best Practice

Attach real CloudWatch Alarms

Configure automatic rollback triggers tied to metrics that actually reflect user-facing health, like error rate or latency.

Best Practice

Test lifecycle hooks in staging first

Validate appspec.yml scripts against a realistic staging environment before trusting them in production.

Mistake

No grace period after traffic cutover

Terminating the old environment immediately after a blue/green switch, removing the ability to roll back quickly if a delayed issue appears.

Mistake

Outdated CodeDeploy Agent

Running an old agent version on EC2 instances that lacks bug fixes or features assumed by newer deployment configurations.

!
Common Mistake

Assuming AllAtOnce is safe for production because “it worked in testing” — testing environments rarely reproduce the real traffic conditions that make a fast, all-at-once cutover risky.

13Real-world & Industry Examples

Safe, automated deployment practices underpin release processes across very different kinds of organizations.

E-commerce Platforms

Retail companies use blue/green deployments through CodeDeploy to release new checkout and inventory features without risking downtime during high-traffic shopping periods.

Media and Entertainment

Streaming services use canary deployments on ECS to gradually roll out new recommendation or playback logic to a small slice of viewers before a full release.

Enterprise IT Departments

Large enterprises use CodeDeploy across on-premises servers and EC2 fleets together, applying consistent deployment rules whether an application runs in the cloud or in a company data center.

What these examples share is not the specific industry, but the shape of the problem: the need to replace running software with new versions frequently, without the swap itself becoming the source of an outage.

14Frequently Asked Questions

A few questions come up in nearly every team’s first serious CodeDeploy evaluation.

Q1Does every deployment target need the CodeDeploy Agent installed?

Only EC2 and on-premises server deployments require the agent — ECS and Lambda deployments are handled entirely through API-driven traffic shifting with no agent involved.

Q2What is the difference between CodeDeploy and CodePipeline?

CodePipeline orchestrates the entire release workflow across multiple stages like source, build, and test, while CodeDeploy specifically handles the deployment stage — getting new code safely onto target compute — and is commonly used as one action inside a CodePipeline pipeline.

Q3Can a deployment be rolled back automatically?

Yes, CodeDeploy supports automatic rollback triggered either by a failed deployment lifecycle event or by a CloudWatch Alarm crossing a configured threshold during the rollout.

Q4Is blue/green deployment always the better choice over in-place?

Not always — blue/green offers stronger safety and faster rollback, but requires provisioning a full parallel environment, which costs more and takes longer to set up than a straightforward in-place update on smaller or lower-risk applications.

Q5Can CodeDeploy deploy the same application to both EC2 and Lambda?

A single CodeDeploy application can have multiple deployment groups, but each deployment group targets one compute platform, so EC2 and Lambda deployments for the same overall system are typically managed as separate deployment groups rather than one combined deployment.

15Summary and Key Takeaways

AWS CodeDeploy takes the genuinely risky moment of swapping running software for a new version and turns it into a controlled, repeatable, and — when configured well — self-healing process. The underlying engineering decisions — which deployment strategy fits the application’s risk tolerance, what a health check should actually verify, how much of the fleet to expose at once — remain the team’s responsibility, because CodeDeploy provides the choreography, not the judgment about what “healthy” really means for your application. Understanding lifecycle hooks, deployment configurations, blue/green versus in-place strategies, and alarm-based rollback is what separates a deployment process teams trust from one that quietly turns routine releases into incidents.

Key Takeaways

  • Deployment target changes the mechanism — EC2 uses an agent and lifecycle hooks, while ECS and Lambda rely on API-driven traffic shifting.
  • Blue/green trades cost for safety — a fully separate environment gives the strongest rollback guarantee but requires more infrastructure.
  • Health checks are only as good as what they verify — a shallow check can mark a broken deployment as successful.
  • Automatic rollback removes reliance on human speed — CloudWatch Alarms can revert a bad release before anyone notices manually.
  • Batch size is a safety-versus-speed dial — smaller batches are safer but slower, larger batches are faster but riskier.
  • Revision integrity matters as much as deployment permissions — controlling who can write a revision is as important as controlling who can trigger a deploy.
  • Deployment history is a debugging asset — knowing exactly which revision reached which environment and when speeds up root-cause analysis.