A fast pipeline = happy developers. A cheap pipeline = happy finance. This lesson teaches the optimization techniques that compound: shave 30 seconds here, skip a run there — across 50 devs it's thousands of dollars/year.
Optimization Techniques (Ranked by Impact)
Cost Model: GitHub Actions Billing
| Runner OS | Cost/min | Multiplier | Guidance |
|---|---|---|---|
| Linux | $0.008 | 1× | Use for everything unless you need Windows/macOS |
| Windows | $0.016 | 2× | .NET only, avoid if possible |
| macOS | $0.08 | 10× | iOS builds only, never for backend |
Quick math: A 5-minute Linux CI job costs $0.04. Running 100 times/day = $4/day = ~$120/month. Saving 2 minutes per run = $48/month saved. At scale (many repos, many devs), optimization pays for itself quickly.
Cost Reduction Strategies
1. Don't run when unnecessary
# Skip CI for docs-only changes
paths-ignore: ['**.md', 'docs/**', 'LICENSE']
# Cancel redundant runs
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
2. Clean up storage
# Artifacts: short retention
retention-days: 3 # Not the default 90!
# Registry: purge old images weekly
az acr run --cmd "acr purge --filter 'api:sha-.*' --ago 30d --keep 10" ...
3. Right-size infrastructure
# AKS: spot nodes for non-prod (up to 90% cheaper)
az aks nodepool add --priority Spot --name spotnodes ...
# Scale to zero at night (non-prod)
az aks nodepool update --min-count 0 --enable-cluster-autoscaler ...
Speed Targets
| Pipeline Type | Target | Why |
|---|---|---|
| PR CI (lint + test) | < 5 min | Developer stays in context |
| Container build + push | < 3 min | Fast iteration on deploys |
| Full CD (CI → prod) | < 15 min | Acceptable time-to-production |
🧠 Recall Check
- What's the single highest-impact optimization for most pipelines?
- A macOS runner costs how many times more than Linux?
- You push 5 commits in 2 minutes to the same branch. With concurrency cancel, how many runs complete?
- Your CI takes 8 minutes. What two techniques would you try first to get it under 5?
Reveal answers
- Dependency caching. Saves 30-60 seconds per job, applies to every single run, zero downside.
- 10×. $0.08/min vs $0.008/min. Never use macOS for backend CI.
- One. The first 4 are cancelled. Only the last (most recent) run completes.
- Caching (if not already) and parallelism (split lint/test/scan into parallel jobs). If tests are the bottleneck, add test sharding.
Next lesson: Observability for Pipelines — measuring what matters.