What CodeBuild does
AWS CodeBuild is a managed build service. You define a build project (where the source is, which environment to run in, which IAM role to use), and CodeBuild starts a fresh build environment for each run, executes the commands in your build specification, uploads the artifacts and streams the logs to Amazon CloudWatch Logs or Amazon S3. There are no build servers to patch or scale.
CodeBuild can run on its own, triggered by webhooks from your Git provider, or as the build and test step inside AWS CodePipeline.
Source providers
A build project can read source from:
- GitHub and GitHub Enterprise Server
- GitLab and GitLab self-managed
- Bitbucket
- Amazon S3, for a zipped source bundle
- AWS CodeCommit
For the Git providers, you can authenticate with a connection in AWS CodeConnections instead of a personal access token, which keeps long-lived tokens out of the project. A note on CodeCommit: it stopped accepting new customers in July 2024 and became available to new customers again in November 2025, according to the CodeCommit document history.
To build automatically on every change, enable a webhook on the project and add filter groups. A filter group combines an event type (such as a push, or a pull request being created or updated) with patterns for the branch, the file path or the commit message, so a push to main can run the release build while pull requests run only the tests.
Build environments and compute
The environment is a container image running on compute that CodeBuild manages:
- Managed images. AWS provides curated Amazon Linux, Ubuntu, Windows and macOS images with common runtimes. In the buildspec you pick runtimes with
runtime-versions; AWS recommends pinning a version, because the default can change when a runtime reaches end of life (available runtimes). - Custom images. Point the project at your own image in Amazon ECR or another registry when you need tools that the managed images do not include.
- EC2 compute, on demand. You choose a compute type (for example
BUILD_GENERAL1_SMALLorBUILD_GENERAL1_LARGE); the machine is destroyed when the build finishes. - Lambda compute. Builds start faster and scale without queuing, but there are real limits: no Docker builds, no privileged mode, no caching, no VPC connectivity, no tools that need root, writes only under
/tmp, and a 15-minute maximum (Lambda compute limitations). It suits small, quick jobs such as linting or packaging a Lambda function. - Reserved capacity fleets. Dedicated EC2 instances that CodeBuild keeps running for you, so builds start without provisioning delay. They can use a custom AMI and a VPC, and they keep running (and billing) while provisioned (reserved capacity fleets).
The build specification
By default, CodeBuild looks for a file named buildspec.yml in the root of the source. You can point the project at another path, or define the buildspec inline in the project. The buildspec reference recommends version: 0.2, in which all commands run in the same shell instance, so cd and exported variables carry over between commands.
This example builds and tests a Node.js application on a standard Linux image:
version: 0.2
env:
variables:
NODE_ENV: "production"
parameter-store:
API_BASE_URL: "/web-app/prod/api-base-url"
secrets-manager:
NPM_TOKEN: "web-app/npm:token"
phases:
install:
runtime-versions:
nodejs: 22
pre_build:
commands:
- echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
- npm ci --include=dev
build:
commands:
- npm run lint
- npm test -- --reporters=default --reporters=jest-junit
- npm run build
post_build:
commands:
- echo "Build finished for commit ${CODEBUILD_RESOLVED_SOURCE_VERSION}"
reports:
unit-tests:
files:
- "junit.xml"
file-format: JUNITXML
artifacts:
files:
- "**/*"
base-directory: dist
cache:
paths:
- "/root/.npm/**/*"
What each part does:
envsets plain variables, readsAPI_BASE_URLfrom AWS Systems Manager Parameter Store and reads thetokenkey of theweb-app/npmsecret from AWS Secrets Manager. CodeBuild masks those values in the logs. The project’s service role needsssm:GetParametersandsecretsmanager:GetSecretValueon exactly those resources.phasesrun in order:install,pre_build,build,post_build. A failing command fails the build.reportssends the JUnit XML file to a report group (created as<project-name>-unit-tests), so test results and trends appear in the console. CodeBuild also accepts formats such as Cucumber JSON, NUnit, TestNG, and coverage reports in Cobertura, JaCoCo, Clover or SimpleCov format.artifactsuploads the contents ofdist. Inside CodePipeline, this becomes the action’s output artifact.cachelists paths to keep between builds.
Do not put secret values under env/variables: those are visible in the console and API. Use the parameter-store or secrets-manager mappings instead. Note that masking matches the exact stored value, so a secret that a command transforms (for example, Base64-encodes) can appear in logs.
Caching
A project can use one of two cache types (build caching):
- Amazon S3 cache stores the paths listed in the buildspec in a bucket, so any build host can restore them.
- Local cache keeps data on the build host and has three modes: source cache, Docker layer cache and custom cache. Docker layer caching is Linux only and needs privileged mode. A local cache is available only to builds that run on the same host. For reserved capacity fleets, AWS recommends using source cache and Docker layer cache.
Reaching private resources: VPC access
By default a build cannot reach resources inside your VPC. Add the VPC ID, private subnets and security groups to the project to run integration tests against an Amazon RDS database, an internal service or a private package repository (VPC support). AWS’s guidance: use private subnets only, and provide a NAT gateway so the build can still reach public endpoints such as GitHub or AWS APIs (an internet gateway alone does not work). Allow no inbound traffic in the build’s security group. VPC connectivity is not supported for shared VPCs.
Practices that keep builds fast and safe
- One role per project, scoped to the buckets, secrets and repositories that project uses.
- Pin runtimes and image versions so builds do not change underneath you.
- Run the fast checks first (lint, unit tests) and fail early.
- Build once, deploy many. Produce one artifact or container image per commit and promote it through environments rather than rebuilding.
- Use Lambda compute for short jobs and EC2 or reserved capacity for Docker builds and long test suites.
How 9Acts can help
9Acts is an AWS Advanced Tier Services Partner with the AWS DevOps Competency and more than 100 AWS certifications across the team. We set up CodeBuild and CodePipeline for application and infrastructure teams, including caching, test reporting, VPC access and secrets handling. See our DevOps services or contact us.
