7 Ways Your CI/CD Pipeline is Wasting Money
7 Ways Your CI/CD Pipeline is Wasting Money
CI/CD isn’t free. Every pipeline run costs money in compute time.
After auditing pipelines for 20+ teams, here are the 7 most common sources of waste – and how to fix them.
1. Running Expensive Compute for Simple Tasks
The waste: Using large CI runners for trivial jobs like linting or markdown checks.
Real example: GitHub Actions workflow running on ubuntu-latest-8-cores runner for ESLint.
ESLint job takes 45 seconds. Using 8-core runner when 2-core would work fine.
Cost:
8-core runner: £0.064/minute
2-core runner: £0.008/minute
Waste: £0.056/minute × 45 seconds = £0.042 per run
With 200 commits/month: £8.40/month wasted on one job.
Fix: Right-size runners per job:
jobs:
lint:
runs-on: ubuntu-latest # 2-core, cheap
steps:
- run: npm run lint
tests:
runs-on: ubuntu-latest-4-cores # Tests need more power
steps:
- run: npm test
e2e:
runs-on: ubuntu-latest-8-cores # E2E tests are heavy
steps:
- run: npm run test:e2e
2. Rebuilding Dependencies Every Time
The waste: Downloading and installing npm/pip/maven packages from scratch on every run.
Real example: Node.js project with 300MB of node_modules.
Every CI run:
- Download packages: 2 minutes
- Install packages: 3 minutes
- 5 minutes of waste per run at £0.008/min = £0.04
200 runs/month = £8/month + 16.6 hours of engineer wait time
Fix: Cache dependencies:
- name: Cache dependencies
uses: actions/cache@v3
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
Now installation takes 15 seconds instead of 5 minutes.
3. Running Tests You Don’t Need
The waste: Running entire test suite when only documentation changed.
Real example: Pull request updating README.md triggers:
- Unit tests: 8 minutes
- Integration tests: 12 minutes
- E2E tests: 15 minutes
- Total: 35 minutes of compute for a markdown file change
Cost: 35 minutes × £0.008/min = £0.28 per documentation PR
With 50 documentation changes/month: £14/month waste
Fix: Use path filters:
on:
pull_request:
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE'
- '.gitignore'
# Or run only specific tests based on changed files
- name: Run unit tests
if: contains(github.event.pull_request.changed_files, 'src/')
run: npm run test:unit
4. Not Failing Fast
The waste: Running expensive tests when quick checks already failed.
Real example: Pipeline structure:
- Linting (1 min) – FAILS
- Unit tests (8 min) – runs anyway
- Integration tests (12 min) – runs anyway
- E2E tests (15 min) – runs anyway
Developer pushes code with linting errors. Pipeline runs for 36 minutes before showing failure.
Cost: 35 wasted minutes × £0.008 = £0.28 per failed run
With 100 failed builds/month: £28/month waste + terrible developer experience
Fix: Order jobs by speed, make later jobs depend on earlier ones:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- run: npm run lint
test:
needs: lint # Only run if lint passes
runs-on: ubuntu-latest-4-cores
steps:
- run: npm test
e2e:
needs: test # Only run if tests pass
runs-on: ubuntu-latest-8-cores
steps:
- run: npm run test:e2e
Now pipeline fails in 1 minute instead of 36 minutes.
5. Duplicate Docker Builds
The waste: Building the same Docker image multiple times per deployment.
Real example: Pipeline that:
- Builds image for testing
- Runs tests
- Builds image again for production (identical)
- Pushes to registry
Each build takes 12 minutes. Building twice = 12 minutes wasted per deployment.
Cost: 12 minutes × £0.032/min (4-core runner) = £0.384 per deployment
50 deployments/month = £19.20/month waste
Fix: Build once, test the image, then tag and push:
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Run tests in container
run: docker run myapp:${{ github.sha }} npm test
- name: Tag for production
run: docker tag myapp:${{ github.sha }} myapp:latest
- name: Push to registry
run: docker push myapp:latest
6. Running CI on Every Branch
The waste: Full CI pipeline runs on experimental feature branches that never get merged.
Real example: Team creates 50 branches/month. Only 20 get merged.
30 abandoned branches × 35 minutes of CI = 1,050 minutes wasted
Cost: 1,050 minutes × £0.008 = £8.40/month on branches that never ship
Fix: Run full pipeline only on important branches:
on:
push:
branches:
- main
- develop
- 'release/**'
pull_request:
types: [opened, synchronize, reopened]
# For feature branches, run lightweight checks only
jobs:
quick-check:
if: github.ref != 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- run: npm run lint
- run: npm run test:unit
full-pipeline:
if: github.ref == 'refs/heads/main' || github.event_name == 'pull_request'
# ... full test suite
7. No Automatic Cleanup of Old Artifacts
The waste: Storing build artifacts, Docker images, and logs forever.
Real example: Company storing:
- GitHub Actions artifacts: 90 days retention (default)
- Docker images in ECR: never deleted
- CI logs: stored indefinitely
Storage costs:
GitHub Actions artifacts: £0.008/GB/day
ECR images: £0.10/GB/month
CloudWatch logs: £0.03/GB/month
After 2 years:
- 500GB of old artifacts
- 200GB of Docker images (10 images per day × 730 days)
- 100GB of logs
Monthly cost:
Artifacts: £120
ECR: £20
Logs: £3
Total: £143/month for old data nobody uses
Fix: Implement retention policies:
# GitHub Actions - set artifact retention
- uses: actions/upload-artifact@v3
with:
retention-days: 7 # Only keep for 1 week
# ECR lifecycle policy
{
"rules": [{
"rulePriority": 1,
"description": "Keep only 10 images",
"selection": {
"tagStatus": "any",
"countType": "imageCountMoreThan",
"countNumber": 10
},
"action": { "type": "expire" }
}]
}
# CloudWatch logs retention
aws logs put-retention-policy
--log-group-name /aws/ci-builds
--retention-in-days 30
The Total Waste
Add up all 7 sources of waste:
| Waste Source | Monthly Cost |
|---|---|
| Oversized runners | £8.40 |
| No dependency caching | £8.00 |
| Unnecessary test runs | £14.00 |
| Not failing fast | £28.00 |
| Duplicate Docker builds | £19.20 |
| CI on unused branches | £8.40 |
| No artifact cleanup | £143.00 |
| Total | £229/month |
Over a year: £2,748 wasted on CI/CD inefficiency
And this is for a single project. Multiply by number of repos…
How We Optimize CI/CD Pipelines
Our Infrastructure Audit includes CI/CD pipeline review:
- Analyze all GitHub Actions / GitLab CI / CircleCI workflows
- Identify waste and bottlenecks
- Implement caching and optimization
- Configure proper artifact retention
- Set up cost monitoring
Typical results:
- 40-60% reduction in CI costs
- 50%+ faster build times
- Better developer experience
Cost: £3,000 (2-week audit + implementation)
Savings: £200-400/month (ROI in ~10 months)
We’ll review your CI/CD setup and estimate potential savings.