AWS CI/CD pipeline is a chain of four services:
Code → CodeCommit → CodeBuild → CodeDeploy → Production
(source) (build/test) (deploy)
Orchestrator: CodePipeline ties them all together
Real-World: Developer pushes code → CodePipeline detects change → CodeBuild runs tests + builds Docker image → CodeDeploy rolls it out to EC2/ECS/Lambda with blue/green deployment.
What it is: Fully managed Git repository hosting (like GitHub, but on AWS).
- Private Git repositories
- IAM-integrated (no separate username/password needed)
- Encrypts at rest (KMS) and in transit (HTTPS/SSH)
- Triggers: send events to Lambda/SNS on push, PR, branch creation
| Method | Use case |
|---|---|
| HTTPS + Git credentials | IAM username/password (generated per user) |
| SSH keys | Upload public key to IAM user |
| AWS CLI credential helper | For EC2 instances with IAM roles |
Key: IAM policies control CodeCommit access — no separate permissions system.
User in Account B needs access to repo in Account A:
- Account A creates IAM role with CodeCommit permissions
- Account A trust policy allows Account B users to assume the role
- Account B user assumes the role → accesses repo
Notification Rules vs Triggers:
- Notification rules: for collaboration (PR comments, approvals) → SNS
- Triggers: for automation (push, PR merge) → Lambda/SNS
What it is: Fully managed CI build service. No servers to manage. You define build steps in buildspec.yml.
version: 0.2
env:
variables:
ENVIRONMENT: production
parameter-store:
DB_PASSWORD: /app/prod/db-password # from SSM Parameter Store
secrets-manager:
API_KEY: prod/api-key:key # from Secrets Manager
phases:
install:
runtime-versions:
nodejs: 18
commands:
- npm install
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REGISTRY
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
build:
commands:
- npm test
- docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_HASH .
- docker push $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_HASH
post_build:
commands:
- echo Build completed on `date`
- # Create imagedefinitions.json for CodeDeploy to ECS
- printf '[{"name":"app","imageUri":"%s"}]' $ECR_REGISTRY/$ECR_REPOSITORY:$COMMIT_HASH > imagedefinitions.json
artifacts:
files:
- imagedefinitions.json
- appspec.yml
- scripts/**/*
cache:
paths:
- node_modules/**/* # Cache node_modules between buildsCodeBuild runs in Docker containers:
- AWS-managed images: Ubuntu, Amazon Linux 2 (pre-built for common languages)
- Custom Docker image: bring your own ECR image
- Runs inside VPC (optional): for accessing private RDS, ElastiCache
| Cache Type | Where stored | Use case |
|---|---|---|
| Local | Build container (same container) | Fastest, same build only |
| S3 | S3 bucket | Cross-build caching, node_modules |
| Amazon CodeBuild layer | Build environment layers | Docker layers |
If build needs to access private resources:
# CodeBuild project VPC configuration
VpcConfig:
VpcId: vpc-abc123
Subnets: [subnet-private-1, subnet-private-2]
SecurityGroupIds: [sg-build-servers]- CodeBuild API (override at run time)
- buildspec.yml env/variables
- Project-level settings
Never put secrets in buildspec.yml variables — use Parameter Store or Secrets Manager.
What it is: Automated deployment service to EC2, on-premises, Lambda, or ECS.
| Target | Deployment Types |
|---|---|
| EC2/On-premises | In-place, Blue/Green |
| Lambda | Canary, Linear, All-at-once |
| ECS | Blue/Green only |
EC2 appspec.yml:
version: 0.0
os: linux
files:
- source: /app
destination: /var/www/app
- source: /config/nginx.conf
destination: /etc/nginx/nginx.conf
permissions:
- object: /var/www/app
owner: www-data
group: www-data
hooks:
BeforeInstall:
- location: scripts/stop_server.sh
timeout: 30
AfterInstall:
- location: scripts/install_dependencies.sh
timeout: 60
ApplicationStart:
- location: scripts/start_server.sh
timeout: 30
ValidateService:
- location: scripts/health_check.sh
timeout: 30Lambda appspec.yml:
version: 0.0
Resources:
- MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Name: checkout-function
Alias: prod
CurrentVersion: 5
TargetVersion: 6
Hooks:
BeforeAllowTraffic: ValidateNewVersion
AfterAllowTraffic: ValidateAfterDeploymentApplicationStop (stop old app)
DownloadBundle (download from S3/GitHub)
BeforeInstall (prep work)
Install (copy files)
AfterInstall (configure)
ApplicationStart (start new app)
ValidateService (health check)
BeforeBlockTraffic / BlockTraffic / AfterBlockTraffic (Blue/Green only)
BeforeAllowTraffic / AllowTraffic / AfterAllowTraffic (Blue/Green only)
EC2 In-Place:
All at once: stop old → deploy new → restart (downtime!)
Rolling: deploy to N instances at a time
Rolling with additional batch: launch extra instances first
Blue/Green (EC2):
Blue (current): Auto Scaling Group v1
Green (new): new ASG created with v2
LB shifts traffic from Blue to Green
Blue decommissioned (or kept for rollback)
Lambda Canary:
10Percent10Minutes: 10% traffic to new version for 10 min, then 100%
Linear10PercentEvery1Minute: add 10% every minute until 100%
AllAtOnce: instant switchover
ECS Blue/Green:
- Creates new task set with new Docker image
- Route traffic gradually or all-at-once
- If health check fails → automatic rollback
{
"autoRollbackConfiguration": {
"enabled": true,
"events": ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM"]
}
}Set CloudWatch alarm on error rate → CodeDeploy auto-rolls back if alarm triggers.
What it is: Orchestrator for CI/CD workflow. Connects source → build → test → deploy.
Stage 1: Source
└── Action: CodeCommit (watch 'main' branch)
Stage 2: Build
└── Action: CodeBuild (run tests + build artifact)
Stage 3: Staging Deploy
└── Action: CodeDeploy (deploy to staging)
Stage 4: Manual Approval
└── Action: Manual (someone clicks approve in console/email)
Stage 5: Production Deploy
└── Action: CodeDeploy (deploy to production)
| Category | Actions |
|---|---|
| Source | CodeCommit, GitHub, ECR, S3 |
| Build | CodeBuild, Jenkins |
| Test | CodeBuild, Device Farm, third-party |
| Deploy | CodeDeploy, CloudFormation, Elastic Beanstalk, ECS, S3 |
| Invoke | Lambda |
| Approval | Manual approval |
Stages can have parallel actions:
Stage: Test
├── Action: Unit Tests (CodeBuild) ─┐
├── Action: Integration Tests ├── Run simultaneously
└── Action: Security Scan (CodeBuild) ┘
All must pass before next stage
Source Stage → produces artifact (source code) → stored in S3
Build Stage → takes source artifact → produces build artifact (JAR/Docker image ref)
Deploy Stage → takes build artifact → deploys
All artifacts encrypted with KMS, stored in S3.
Account: Tools (CodePipeline lives here)
↓
Account: Dev (CodeDeploy deploys here)
Account: Prod (CodeDeploy deploys here)
Requires cross-account IAM roles and KMS key policies.
Pipeline events → EventBridge → SNS → email/Slack
→ Lambda → custom workflow
What it is: Managed artifact repository (npm, pip, Maven, NuGet packages).
Developers → CodeArtifact (private packages) ← proxies → npm/PyPI/Maven public
→ CodeBuild (uses packages from CodeArtifact)
Why: Control which packages your team can use. Cache public packages internally. Share private packages across accounts.
| Practice | Reason |
|---|---|
| Never put secrets in buildspec.yml | Exposed in build logs |
| Use blue/green for zero-downtime deploys | Roll forward or back without downtime |
| Require manual approval before prod | Human check before production changes |
| Set auto-rollback triggers on CloudWatch alarms | Fast recovery from bad deploys |
| Cache dependencies in CodeBuild | Faster builds = faster feedback |
| Use CodePipeline artifact encryption with CMK | Compliance, audit trail |
| Run parallel tests in CodeBuild | Faster pipeline |
| Anti-Pattern | Impact | Fix |
|---|---|---|
| Deploying directly to prod without staging | Breaking changes in production | Add staging stage with integration tests |
| No rollback strategy | Downtime when deploy fails | Configure auto-rollback |
| Running CodeBuild without VPC when accessing private resources | Build fails, security gaps | Configure VPC for CodeBuild |
| Storing artifacts in same account as production | Blast radius if tools account compromised | Separate accounts |
| No manual approval before prod | Accidental bad deploys | Add approval action |
- CodeDeploy appspec.yml defines the deployment. Must be at root of repository.
- CodeBuild buildspec.yml defines the build. Can override location.
- Lambda deployments: CodeDeploy handles canary/linear shifts — NOT CodePipeline.
- EC2 CodeDeploy: requires CodeDeploy Agent running on instances.
- CodeDeploy rollback: creates a NEW deployment (reversal), not literally rolling back.
- CodePipeline stages must complete in order. Actions within a stage can be parallel.
- CodeCommit notifications vs triggers: Notifications = collaboration. Triggers = automation.
- S3 as source: CodePipeline can watch an S3 bucket for new ZIP files → trigger pipeline.
- Cross-region deployments: CodePipeline supports cross-region actions with regional S3 artifact buckets.
Q: Deploy Lambda with 10% traffic for 10 minutes then shift 100%?
→ CodeDeploy with Canary10Percent10Minutes deployment config.
Q: Build process needs to access private RDS? → Configure CodeBuild VPC to run inside your VPC.
Q: Secrets needed during build?
→ Store in SSM Parameter Store or Secrets Manager, reference in buildspec.yml env.parameter-store.
Q: Automatic rollback when error rate exceeds 5%? → CodeDeploy auto-rollback + CloudWatch alarm on error rate.
Q: Require human approval before production deployment? → Add Manual Approval action in CodePipeline before production deploy stage.
Q: Pipeline should deploy to multiple regions? → CodePipeline cross-region actions with S3 buckets in each region.