← All field notes
Platform 5 min read

7 Ways Your CI/CD Pipeline is Wasting Money

Most teams waste £200+/month on CI/CD inefficiency. Here are the 7 most common sources of waste and how to fix them.

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:

  1. Linting (1 min) – FAILS
  2. Unit tests (8 min) – runs anyway
  3. Integration tests (12 min) – runs anyway
  4. 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:

  1. Builds image for testing
  2. Runs tests
  3. Builds image again for production (identical)
  4. 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)

Book a Discovery Call

We’ll review your CI/CD setup and estimate potential savings.

AS

Written by Alan Son

CTO judgment, grounded in delivery.

I build commercial AI products and help founders turn ambitious technical ideas into reliable production systems.

More about my work

Need an experienced technical partner?

Let’s work out the right next move.