Skip to content
AWS aws deployment 5 min read

AWS CodeBuild

AWS CodeBuild is a fully managed continuous integration (CI — the practice of automatically compiling and testing your code every time it changes) service. You hand it your source code and a small set of instructions, and CodeBuild spins up a fresh container, runs your build, runs your tests, and produces output files (called “artifacts”). You never manage a build server, and you pay only for the compute minutes a build actually uses. This makes it the natural “build” stage inside a larger release pipeline.

When to use CodeBuild (and when not to)

Use CodeBuild when you want repeatable, on-demand builds without owning a Jenkins box or keeping a build machine running 24/7. It shines as the middle stage of an automated pipeline: source comes in, CodeBuild compiles and tests it, and the result is deployed.

Do not reach for CodeBuild if you need a build environment that stays alive between runs (it does not — see the gotcha below), or if you already have a mature self-hosted CI system you are happy with. For very long-running or GPU-heavy jobs, also compare costs against a dedicated EC2 instance (a virtual server you rent by the hour).

OptionManaged?BillingBest for
CodeBuildYesPer build minuteOn-demand CI in an AWS pipeline
Self-hosted Jenkins on EC2NoPer running hourHeavy customization, always-on
GitHub ActionsYesPer minute (GitHub)Repos already on GitHub

How a build is defined: buildspec.yml

CodeBuild reads its instructions from a file called buildspec.yml in the root of your source. This YAML file lists the commands to run in named phases. A typical Node.js build looks like this:

version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 22
    commands:
      - npm ci
  build:
    commands:
      - npm run build
      - npm test
artifacts:
  files:
    - "**/*"
  base-directory: dist
cache:
  paths:
    - "node_modules/**/*"

The phases run in order: install, then pre_build (optional), build, then post_build (optional). The artifacts block tells CodeBuild which files to package and ship to Amazon S3 (Simple Storage Service — AWS object storage) or pass to the next pipeline stage.

The no-persistent-workspace gotcha

Every CodeBuild run starts in a brand-new, empty container. Nothing you downloaded last time is there. If you do not configure caching, every single build re-downloads all your dependencies from scratch — which is slow and adds billable minutes.

Because there is no persistent workspace, you must opt in to caching explicitly. Add a cache block to your buildspec (shown above) and choose a cache backend on the project:

  • S3 cache — stored in an S3 bucket, shared across all builds. Best for most teams.
  • Local cache — kept on the build host briefly; faster but only helps back-to-back builds.

Without this, a project that takes 90 seconds with a warm cache can take 4+ minutes cold, every time.

Creating a build project (Console)

  1. Open the CodeBuild console and choose Create build project.
  2. Under Project configuration, give it a name like my-app-build.
  3. Under Source, pick your provider (CodeCommit, GitHub, or S3) and the repository.
  4. Under Environment, choose a managed image (for example, the Amazon Linux standard image), set the compute size, and select New service role so CodeBuild creates an IAM role for itself.
  5. Under Buildspec, leave Use a buildspec file selected (it reads buildspec.yml from your repo).
  6. Under Artifacts, choose Amazon S3 and pick a bucket, or No artifacts if a pipeline handles output.
  7. Expand Additional configuration and enable Cache (Amazon S3) to avoid the cold-build problem.
  8. Choose Create build project, then Start build.

Creating a build project (CLI)

With AWS CLI v2, define the project in a JSON file and create it:

aws codebuild create-project \
  --name my-app-build \
  --source type=CODECOMMIT,location=https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-app \
  --artifacts type=S3,location=my-build-artifacts-bucket \
  --cache type=S3,location=my-build-artifacts-bucket/cache \
  --environment type=LINUX_CONTAINER,image=aws/codebuild/amazonlinux-x86_64-standard:5.0,computeType=BUILD_GENERAL1_SMALL \
  --service-role arn:aws:iam::123456789012:role/codebuild-my-app-build-role

Then trigger a build:

aws codebuild start-build --project-name my-app-build

Output:

{
    "build": {
        "id": "my-app-build:7f3c1a2b-9d4e-4f6a-8b2c-0a1b2c3d4e5f",
        "buildStatus": "IN_PROGRESS",
        "projectName": "my-app-build",
        "currentPhase": "QUEUED"
    }
}

The IAM service role does the work, not you

This is the second common trap. When CodeBuild runs, it acts as its own IAM (Identity and Access Management — AWS’s permissions system) service role, not as your user. Your personal permissions are irrelevant once the build starts.

So if your build needs to read source artifacts from S3, push a Docker image to Amazon ECR (Elastic Container Registry — AWS’s private image store), or read a secret, those permissions must be attached to the CodeBuild service role. A build that fails with AccessDenied is almost always a missing permission on this role, not on your account.

aws iam attach-role-policy \
  --role-name codebuild-my-app-build-role \
  --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser

Grant the service role only what the build needs. A build role with broad admin access is a real security risk, because anyone who can edit buildspec.yml can then run arbitrary AWS commands with those permissions.

Cost note

CodeBuild bills per build minute by compute size. As a rough 2026 guide, the smallest Linux tier (BUILD_GENERAL1_SMALL) costs about $0.005 per minute, so a 3-minute build is roughly 1.5 cents. There is a monthly free tier of 100 build minutes on that small tier. The cheapest way to cut the bill is good caching — fewer minutes per build means lower cost directly.

Best Practices

  • Always configure an S3 or local cache and a matching cache block in buildspec.yml — cold builds waste time and money.
  • Scope the CodeBuild service role to the minimum permissions the build actually needs (least privilege).
  • Pin runtime-versions in your buildspec so builds are reproducible and do not silently change when AWS updates default versions.
  • Store secrets in AWS Secrets Manager or Systems Manager Parameter Store and reference them, never hard-code them in the buildspec.
  • Keep build logs in Amazon CloudWatch Logs (turned on by default) to debug failures quickly.
  • Use a small compute size by default and scale up only for builds that genuinely need it.
Last updated June 15, 2026
Was this helpful?