How to reduce CI/CD costs
./optimize --proven-strategies
Ten optimisation techniques that consistently cut CI/CD spend, ranked by impact-to-effort. Each comes with a typical savings range and a one-paragraph implementation note. Pick the top two or three for your stack and you'll usually halve your monthly CI bill in a sprint.
Cache dependencies aggressively
saves 20-50%Most pipelines spend 40-70% of build time on npm install / pip install / gradle build. Cache the dependency directory and the lock file together. Restore on cache hit, install only on miss. Every major CI/CD platform has a built-in cache action. This is the highest-impact single change you can make.
Skip jobs when nothing changed
saves 20-40%Use path filters (paths: in GitHub Actions, rules: changes: in GitLab CI) so backend-only commits don't trigger frontend tests, and docs commits don't trigger anything. On busy monorepos this single change often pays for the entire optimisation effort.
Run heavy jobs only on protected branches
saves 10-30%Full integration tests, performance benchmarks, and Cypress runs don't need to fire on every PR commit. Restrict them to main, release branches, or scheduled cron jobs. PR checks become fast lint + unit tests; deeper runs happen on merge.
Use spot / preemptible instances for self-hosted runners
saves 60-80% on computeSpot instances on AWS or preemptible VMs on GCP cost 60-80% less than on-demand. CI jobs are idempotent so reclamation is harmless: the agent dies, the orchestrator retries on a fresh instance. Just don't put long-running deploy steps on spot.
Right-size your runners
saves 15-30%A 4-core runner finishing in 4 minutes can be cheaper than a 2-core finishing in 12. Time the trade-off, don't assume the cheap runner wins. CircleCI's resource_class, GitHub Actions' larger_runner labels, and GitLab CI's tags: all let you target specific machine sizes per job.
Split slow test suites across parallel runners
saves wall-clock 50-80%, billable similarknapsack_pro, ts-jest --shard, pytest-split, CircleCI --split-by=timings: all let you carve a 30-minute test run into ten 3-minute parallel jobs. Total billable minutes stay similar but PR feedback latency drops dramatically. Faster feedback means fewer retries means fewer billable minutes overall.
Set artifact retention to days, not months
saves $5-50/month per repoDefault retention on GitHub Actions is 90 days. Most artifacts are useful for 7-14. Drop retention with retention-days: 7 in your workflow yaml. Multiply across repos and you're saving real storage cost, especially on the Free and Team plans where storage past the included quota is billed at $0.25/GB/month.
Reduce Docker image rebuild work
saves 10-25%Use multi-stage Dockerfiles with deterministic layer ordering, push intermediate stages as cache to a registry, and pull them on subsequent builds. Tools like docker buildx with type=registry caching make this almost automatic. A 6-minute image rebuild becomes 30 seconds when layers are cached properly.
Move artefacts off platform-billed storage
saves $10-100/monthMost CI/CD platforms charge premium rates for artifact storage. Push large artefacts (tarballs, Docker images, video recordings of e2e runs) to S3 or GCS instead. Standard cloud storage is 10-100x cheaper than CI/CD platform-included storage past the free tier.
Set hard spending limits
saves the runaway-loop billEvery platform supports a spending cap. Set one. A single misconfigured workflow that triggers on every push of every branch can rack up four-figure bills overnight. Spending limits won't stop bad workflows but they'll stop the invoice. GitHub Actions, GitLab CI, and CircleCI all support hard caps at the org level.
Suggested order of work
- 01. Set spending limits today. Five-minute job, prevents disaster.
- 02. Add caching to your slowest install step. Ship in a day.
- 03. Add path filters to skip irrelevant jobs. Half a day on a monorepo.
- 04. Move artifact retention from default to 7-14 days. Five-minute change.
- 05. Move heavy jobs off PR triggers. Few hours, big PR latency win.
- 06. Right-size runners using actual job timings. One-week measurement.
- 07. Evaluate self-hosted runners for hot paths. Only if you're past 50K minutes / month.
Related guides
Frequently Asked Questions
# click any question to expand