CI/CD on AWS with CodePipeline, CodeBuild and CodeDeploy

Khimananda Oli 7 min read Database
CI/CD on AWS with CodePipeline, CodeBuild and CodeDeploy

By Khimananda Oli | Last reviewed: August 2026

Shipping code reliably requires an automated pipeline that integrates testing, building, and deployment without manual intervention. Implementing CI/CD on AWS with CodePipeline, CodeBuild and CodeDeploy provides a fully managed, integrated workflow that eliminates Jenkins maintenance overhead while keeping your infrastructure within the AWS ecosystem. This guide walks through the practical configuration of these services for a production-grade application, focusing on security, reproducibility, and audit readiness.

How does CI/CD on AWS with CodePipeline, CodeBuild and CodeDeploy work together?

Understanding the distinct responsibility of each service prevents architectural confusion. In practice, many teams conflate these tools, but AWS designed them as modular components. CodePipeline acts solely as the orchestrator; it holds no compute state and performs no builds itself. It simply moves artifacts between stages based on triggers and approvals. CodeBuild is the ephemeral compute engine that runs your buildspec commands, installs dependencies, and produces artifacts. CodeDeploy is the specialized agent manager that executes deployment lifecycle hooks on target instances.

Source (GitHub)CodePipeline(Orchestrator)CodeBuild(Test & Package)CodeDeploy(Rolling Deploy)EC2 / ECS
CI/CD on AWS with CodePipeline, CodeBuild and CodeDeploy: orchestration flow from source to production targets

This separation matters for compliance. When preparing for SOC 2 or ISO 27001 audits, you can demonstrate that build environments are ephemeral (CodeBuild), deployment permissions are scoped narrowly (CodeDeploy IAM roles), and pipeline changes require approval gates (CodePipeline manual actions). For teams evaluating alternatives, understanding this architecture helps when comparing options like GitHub Actions vs GitLab CI.

How do you configure CodeBuild for reproducible artifact generation?

CodeBuild relies entirely on the buildspec.yml file at your repository root. A common mistake is installing dependencies during every build without caching, which inflates costs and duration. Always define cache paths explicitly and pin runtime versions rather than relying on "latest" tags.

Production-ready buildspec.yml example

version: 0.2

env:
  variables:
    NODE_ENV: production
    ARTIFACT_BUCKET: my-app-artifacts-prod
  parameter-store:
    DB_HOST: /prod/app/db_host
    API_KEY: /prod/app/api_key

phases:
  install:
    runtime-versions:
      nodejs: 22
    commands:
      - npm ci --prefer-offline --no-audit
  build:
    commands:
      - npm run lint
      - npm run test:ci
      - npm run build
  post_build:
    commands:
      - aws s3 cp dist/ s3://$ARTIFACT_BUCKET/$CODEBUILD_RESOLVED_SOURCE_VERSION/ --recursive

artifacts:
  files:
    - '/*'
  base-directory: dist
  discard-paths: no

cache:
  type: S3
  location: $ARTIFACT_BUCKET/cache/node-modules.zip
  paths:
    - node_modules//*

Key points from this configuration that I enforce in every project:

  • Use npm ci over npm install: Guarantees deterministic installs matching package-lock.json exactly.
  • Parameter Store integration: Secrets never appear in logs or environment variable plaintext. CodeBuild fetches them at runtime with IAM-scoped access.
  • S3 caching: Reduces subsequent build times by 40–60% for Node.js projects. Local caching is faster but unavailable across availability zones.
  • Explicit runtime versions: Prevents surprise breakage when AWS updates default images.

If you are containerizing your application before deployment, pair this build process with Docker multi-stage builds to minimize image size before pushing to ECR.

How do you set up CodeDeploy for zero-downtime EC2 deployments?

CodeDeploy requires two artifacts: the application revision (your built code) and the AppSpec file (appspec.yml) that defines lifecycle hooks. For EC2 deployments, the CodeDeploy agent must be pre-installed and running on every target instance. I recommend baking this into your AMI via Packer or user-data scripts rather than installing it ad-hoc.

AppSpec configuration with validation hooks

version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/myapp
    overwrite: true

hooks:
  BeforeInstall:
    - location: scripts/cleanup.sh
      timeout: 300
      runas: root
  AfterInstall:
    - location: scripts/install-deps.sh
      timeout: 600
      runas: deploy
  ApplicationStart:
    - location: scripts/start-service.sh
      timeout: 300
      runas: deploy
  ValidateService:
    - location: scripts/health-check.sh
      timeout: 120
      runas: deploy

The ValidateService hook is non-negotiable for production. Your health-check script should curl the local endpoint and return a non-zero exit code if the app fails to start. Without this, CodeDeploy marks the deployment as successful even if the application crashes immediately after launch. For deeper strategies, see blue-green vs canary deployment comparisons.

CodeDeployEC2 AgentApplicationBeforeInstallAfterInstallStart ServiceHealth CheckSuccess Signal
CodeDeploy lifecycle hook sequence ensuring validated deployments within CI/CD on AWS with CodePipeline, CodeBuild and CodeDeploy

What are the critical IAM and security configurations for AWS CI/CD?

Security misconfigurations in CI/CD pipelines are among the top causes of cloud breaches. Every service needs its own least-privilege IAM role. Never reuse the same role for CodeBuild and CodeDeploy, and never attach AdministratorAccess to any pipeline-related role.

ServiceMinimum Required PermissionsCommon Over-Permission Risk
CodePipeline Service Roles3:GetObject/PutObject (artifact bucket only), codebuild:StartBuild/BatchGetBuilds, codedeploy:CreateDeployment/GetDeployments3:* on all buckets allows lateral movement if pipeline is compromised
CodeBuild Service Rolelogs:CreateLogGroup/Stream/PutLogEvents, s3:GetObject/PutObject (specific prefix), ssm:GetParameters (specific path)ec2:* or iam:PassRole enables privilege escalation during builds
CodeDeploy Service Roleec2:Describe*, autoscaling:CompleteLifecycleAction, s3:GetObject (revision bucket)ec2:TerminateInstances allows destructive actions during deploys
EC2 Instance Profiles3:GetObject (artifact bucket prefix only), codedeploy:PutHostUpdateFull S3 read exposes secrets from other projects

For teams handling sensitive data or operating under compliance frameworks, store all deployment credentials in AWS Systems Manager Parameter Store or Secrets Manager. Reference them in buildspec using the parameter-store or secrets-manager blocks shown earlier. Audit CloudTrail logs regularly for unauthorized AssumeRole calls against your pipeline roles. If you manage infrastructure alongside your pipeline, apply principles from Infrastructure as Code with Terraform to version-control these IAM policies.

How do you optimize cost and performance for AWS CI/CD pipelines?

AWS CI/CD services charge per minute (CodeBuild) and per pipeline execution (CodePipeline). Unoptimized pipelines drain budgets silently. Track your spend proactively using tactics outlined in AWS cost optimization strategies, and apply these pipeline-specific optimizations:

  1. Right-size CodeBuild compute types: Default BUILD_GENERAL1_SMALL ($0.005/min) suffices for most Node.js/Python apps. Only upgrade to MEDIUM or LARGE for Java/Gradle or parallel test suites. Monitor duration metrics in CloudWatch before upsizing.
  2. Enable S3 transfer acceleration selectively: Only useful if your team uploads artifacts from distant regions. For single-region deployments, standard S3 transfers avoid the premium.
  3. Batch dependent builds: Instead of triggering separate pipelines for lint, test, and build, combine them into sequential phases within one buildspec. Each additional pipeline stage adds ~$1/month plus transition latency.
  4. Use reserved capacity for predictable workloads: If you run >300 build minutes daily, CodeBuild reserved capacity reduces costs by up to 40%. Analyze 90-day usage first.
  5. Clean up old artifacts automatically: Set S3 lifecycle policies to expire build artifacts after 30 days. Accumulated GBs in artifact buckets become invisible line items.
UnoptimizedOptimized18 min avg$0.09/build7 min avg$0.035/buildCache + Right-size60% faster · 61% cheaperSavings Source• npm ci + cache• SMALL compute
Cost and duration impact of optimizing CI/CD on AWS with CodePipeline, CodeBuild and CodeDeploy through caching and right-sizing

Implementing Secure and Scalable CI/CD on AWS with CodePipeline, CodeBuild and CodeDeploy

Building effective CI/CD on AWS with CodePipeline, CodeBuild and CodeDeploy requires disciplined configuration beyond basic tutorials. Pin runtime versions, enforce least-privilege IAM, validate every deployment with health checks, and monitor build metrics before scaling compute. These practices separate fragile demo pipelines from production systems that pass audits and survive traffic spikes. If your team needs help designing or hardening an AWS-native pipeline that meets compliance requirements, reach out to discuss your specific architecture.

Frequently Asked Questions

CodePipeline orchestrates the workflow, CodeBuild compiles and tests code in managed containers, and CodeDeploy automates application deployment to EC2, Lambda, or ECS. They function as distinct but integrated services within the AWS CI/CD ecosystem for end-to-end automation.

CodePipeline costs $1 per active pipeline monthly. CodeBuild charges per build minute based on compute type, typically around $0.005 for standard instances. CodeDeploy is free for EC2 and Lambda deployments, making total costs highly dependent on build frequency and duration.

Yes. GitHub Actions offers tighter repository integration and a larger marketplace. However, CodePipeline provides native AWS IAM security, VPC support, and deeper integration with AWS services like ECR and S3 without managing external OIDC connections or secrets.

Configure CodeBuild to output a ZIP file to an S3 artifact bucket defined in your buildspec.yml. CodePipeline automatically manages this transfer. Ensure the artifact name matches exactly in both the build phase output and the deploy phase input configuration settings.

Yes. CodeDeploy natively supports blue-green deployments for Amazon ECS services. It creates a new task set, shifts traffic gradually using Application Load Balancer listeners, and terminates the old task set only after successful validation and health checks complete.

The CodeBuild service role lacks required IAM policies. Attach AWSCodeBuildDeveloperAccess or custom policies granting s3:GetObject, s3:PutObject, and logs:CreateLogStream permissions. Verify the trust relationship allows codebuild.amazonaws.com to assume the role correctly in 2026.

Use a PHP runtime image in buildspec.yml. Install dependencies via Composer, configure .env.testing, and execute vendor/bin/phpunit. Cache the vendor directory in S3 to speed up subsequent builds and ensure database migrations run against a test RDS instance.

Yes. Configure your source stage connection to filter by tag patterns. When using CodeStar Connections or GitHub Enterprise, specify the tag glob pattern in the webhook filters to ensure pipelines only execute for release candidates or production version tags.

No, but it simplifies dependency management. You can alternatively use .npmrc with tokens stored in Secrets Manager. CodeArtifact eliminates token rotation overhead and provides upstream proxying, reducing external registry failures during builds in isolated VPC environments.

Check CloudWatch Logs for the specific deployment group and instance. Review the AppSpec file hooks section for script errors. Use aws deploy get-deployment-instance to inspect exit codes and stderr output directly from the command line for immediate diagnosis.

Standard, ARM, GPU, and Windows Server containers are available. Standard Linux x86_64 remains most common for web apps. ARM instances offer twenty percent cost savings for compatible workloads. Select compute matching your production architecture to avoid cross-compilation issues.

Never hardcode credentials in buildspec.yml. Reference AWS Secrets Manager or Systems Manager Parameter Store parameters using the env parameter-store or secrets-manager blocks. CodeBuild retrieves values at runtime and masks them automatically in CloudWatch Logs output streams.

Yes. Define infrastructure changes in a dedicated pipeline stage running CodeBuild with Terraform CLI. Store state in S3 with DynamoDB locking. Use manual approval actions before apply stages to prevent accidental production infrastructure modifications during automated CI/CD executions.

Cold starts typically take thirty to ninety seconds. Enable reserved capacity or use cached Docker layers to reduce initialization time. Pre-built custom images stored in ECR start faster than building base images dynamically during each pipeline execution cycle.

Yes. Configure multiple actions within a single stage to run simultaneously by setting RunOrder to the same value. This parallelizes independent tasks like linting and unit testing, significantly reducing total pipeline duration compared to sequential action execution.