← Back to libraryQuestion 221 of 273
🔧CI/CDIntermediate

Build & Test Stages (Fail-Fast Ordering)

📌 Definition:

Fail-fast ordering arranges pipeline stages so the fastest, cheapest checks run first and a failure stops the pipeline immediately, avoiding wasted time and compute on work that can no longer succeed.

📖 Detailed Explanation:

A well-ordered pipeline is a funnel: lint and type-check (seconds) → build → unit tests → integration/API → E2E → deploy. If linting fails, there's no reason to run a 10-minute E2E suite, so the pipeline should short-circuit. In GitHub Actions this is expressed with job dependencies (needs:) and, within a matrix, the fail-fast option that cancels sibling jobs when one fails. The goal is to give the developer the earliest possible actionable signal and to conserve CI minutes (which cost money and queue time). There's a tension to manage: fail-fast within a matrix can hide whether a failure is browser-specific, so for cross-browser test matrices teams often set fail-fast: false deliberately to see the full picture, while keeping fail-fast ordering between stages.

🔑 Key Points:
  • Order stages cheap→expensive: lint/type-check → build → unit → API → E2E → deploy
  • A failed early stage should stop later stages (needs:) to save time and cost
  • Matrix fail-fast cancels sibling jobs on first failure — good for speed
  • For cross-browser matrices, fail-fast: false shows the full failure picture
  • Balance: fail-fast between stages, but full visibility within test matrices
🌍 Real-World Example:

A PR with a syntax error used to burn 12 minutes running the whole suite before failing on build. After reordering with a lint+type-check job that everything else needs, the same PR now fails in 20 seconds with a clear lint error, and no E2E minutes are wasted.

📎 Code Example:
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run lint && npm run type-check

  unit:
    needs: lint          # only runs if lint passed
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

  e2e:
    needs: unit          # gated behind cheaper stages
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false   # see ALL browser results, not just the first failure
      matrix:
        browser: [chromium, firefox, webkit]
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npx playwright test --project=${{ matrix.browser }}
🎯 Scenario-Based Interview Question:

Scenario: Your cross-browser E2E matrix uses the default fail-fast behavior. A WebKit-only bug appears, but because Chromium fails first for an unrelated flaky reason, the whole matrix is cancelled and you never see the WebKit result. How do you configure this correctly?