GitHub Actions Tutorial β Fail-Fast & Parallel
Fail-Fast & Parallel
By default, matrix jobs run in parallel and GitHub cancels all remaining jobs if any single job fails. You can control both behaviors.
Fail-Fast (Default: true)
When fail-fast is true (the default), one failing job cancels all other running matrix jobs:
strategy:
fail-fast: true # default
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
runs-on: ${{ matrix.os }}
steps:
- run: npm test
Job 1 (ubuntu/18) β
success
Job 2 (ubuntu/20) β fails β triggers cancellation
Job 3 (ubuntu/22) π« cancelled
Job 4 (windows/18) π« cancelled
Job 5 (windows/20) π« cancelled
...remaining jobs π« cancelled
Disable Fail-Fast
Set fail-fast: false to let all jobs complete regardless of failures:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
runs-on: ${{ matrix.os }}
steps:
- run: npm test
Job 1 (ubuntu/18) β
success
Job 2 (ubuntu/20) β failure
Job 3 (ubuntu/22) β
success β still runs
Job 4 (windows/18) β
success β still runs
Job 5 (windows/20) β failure
...all jobs run to completion
Use fail-fast: false when:
- You want to see which combinations fail (cross-platform testing)
- Failures are expected in experimental combinations
- You need complete test results for reporting
Max-Parallel
Limit the number of jobs running simultaneously:
strategy:
max-parallel: 3
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
runs-on: ${{ matrix.os }}
Batch 1: Job 1, Job 2, Job 3 (run in parallel)
Batch 2: Job 4, Job 5, Job 6 (start after batch 1 finishes)
Batch 3: Job 7, Job 8, Job 9 (start after batch 2 finishes)
Use max-parallel when:
- Deploying to shared environments (avoid conflicts)
- Rate-limited external APIs
- Conserving runner minutes on expensive runners (macOS)
Combining Fail-Fast and Max-Parallel
strategy:
fail-fast: false
max-parallel: 2
matrix:
environment: [dev, staging, production]
region: [us-east-1, eu-west-1]
runs-on: ubuntu-latest
steps:
- run: echo "Deploying to ${{ matrix.environment }} in ${{ matrix.region }}"
This deploys to 6 combinations, 2 at a time, without cancelling on failure.
Continue-on-Error for Matrix Jobs
Mark individual matrix combinations as allowed to fail:
strategy:
fail-fast: false
matrix:
node: [18, 20, 22]
include:
- node: 22
experimental: true
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.experimental || false }}
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm test
If Node 22 fails, the overall workflow still shows as passing because continue-on-error is true for that combination.
Common Mistakes
| Mistake | Fix |
|---|---|
| All jobs cancel when one fails | Set fail-fast: false |
| Too many parallel jobs hit rate limit | Use max-parallel: N |
| Experimental build fails the workflow | Use continue-on-error with include |
max-parallel: 1 is very slow |
Only use serial execution when required |
Quick Reference
| Option | Default | Purpose |
|---|---|---|
fail-fast |
true |
Cancel remaining on first failure |
max-parallel |
Unlimited | Limit concurrent jobs |
continue-on-error |
false |
Allow individual job failure |
β Previous: Include & Exclude
Next: Dynamic Matrix β