C.W.K.
Stream
Lesson 12 of 13 · published

Fail Fast

~9 min · fail-fast, ordering, pipeline-design

Level 0Apprentice
0 XP0/101 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

Cheap checks before expensive ones

If lint takes 30 seconds and tests take 8 minutes, run lint first. If it fails, the tests don't run at all — you save 8 minutes per failed PR. The principle generalizes:

  1. Format check (5 sec) — first.
  2. Lint (30 sec) — second.
  3. Type check (1–3 min) — third.
  4. Unit tests (2–10 min) — fourth.
  5. Integration / e2e tests (5–30 min) — fifth.
  6. Performance budget / smoke deploys — last.

The job-level needs: graph encodes this. fail-fast at the matrix level encodes the same idea within a single job's parallelism.

Counter-pattern: parallelize for visibility

On main, you may want the opposite: run everything in parallel and report all failures at once. This is the 'tell me everything that's broken' mode for retrospective analysis. Most teams use fail-fast on PRs and full-parallel on main.

Code

Fail-fast pipeline shape·yaml
jobs:
  format:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ruff format --check .

  lint:
    needs: format
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ruff check .

  type-check:
    needs: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: mypy src --strict

  test:
    needs: type-check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pytest -q

External links

Exercise

Sketch your current CI as a DAG. Identify the cheapest check that's currently downstream of an expensive one. Move it upstream. Push and time the next failed PR — cycles saved.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.