Am I Billed When a Job Fails?

Yes. A failed GitHub Actions job bills every minute its machine ran, so the lever is failing fast: matrix fail-fast, job timeouts, and cheap checks first.

Yes. A GitHub Actions job that fails held a real machine for the minutes it ran, and those minutes bill at the same rate as the minutes of a job that passes, because the meter reads execution time and the red or green conclusion is metadata written afterwards. No refund path exists for a failed job, so the lever that moves the bill is making failures land early: matrix fail-fast, job timeouts, and cheap checks ordered ahead of expensive ones.

Answer

Billing follows minutes rather than outcomes. GitHub "rounds the minutes and partial minutes each job uses up to the nearest whole minute" (GitHub Actions minute multipliers, checked on 2026-08-13), and WarpBuild bills GitHub Actions runners per minute at the rates on the pricing page and in the cloud runners documentation. A 9 minute job that fails on its last step bills 9 minutes on both platforms.

Here is what a single failed 9 minute attempt costs on each WarpBuild runner type in the table.

Runner labelShapeRateCost of one failed 9 minute attempt
warp-ubuntu-latest-x64-4x4 vCPU, 16 GB$0.008/min$0.072
warp-ubuntu-latest-arm64-4x4 vCPU, 16 GB$0.006/min$0.054
warp-windows-latest-x64-4x4 vCPU, 16 GB$0.016/min$0.144
warp-macos-latest-arm64-6x6 vCPU, 22 GB$0.08/min$0.720

Rates from the pricing page, checked on 2026-08-13. The platform column is the reason a failing iOS job deserves more attention than a failing Linux job: the same 9 wasted minutes bill $0.720 on the macOS label against $0.072 on the 4 vCPU Linux x64 label.

Two things do escape the meter. A job that never starts bills nothing, because GitHub documents that "if a job fails or is skipped, all jobs that need it are skipped" (workflow syntax, checked on 2026-08-13), and a skipped job claims no machine. A job that stops partway bills only the minutes it ran, which is how a cancelled GitHub Actions job is billed. Every technique below is one of those two mechanics applied on purpose.

Detail

The assumptions behind the numbers on this page

  • 900 pull request workflow runs a month on one repository.
  • 18 percent of those runs fail on the first attempt, which is 162 failing runs and 738 passing ones.
  • The expensive job is a 12 leg test matrix on warp-ubuntu-latest-x64-4x at $0.008 per minute, each leg 9 minutes, so a full run of the matrix bills 108 minutes and $0.864.
  • When a run fails, the first red leg surfaces at minute 2, and cancellation reaches the other 11 legs by minute 3.
  • 70 percent of failing runs get re-run in full, which is 113 re-runs.
  • 60 percent of first-attempt failures are lint or type errors, which is 97 runs a 2 minute gate would catch.
  • The gate runs on warp-ubuntu-latest-x64-2x at $0.004 per minute, so it costs $0.008 per run.
  • Three macOS jobs a month hang and sit until a timeout stops them, on warp-macos-latest-arm64-6x at $0.08 per minute.

Replace the run count, the failure rate, and the leg duration with your own before trusting the totals. The reports section below is where those three numbers come from.

The three levers and the minutes each one removes

LeverMinutes it removes per monthEffect on the bill
fail-fast on the test matrix11,826 runner minutes (162 failures x 73 minutes)$94.61
timeout-minutes on the macOS job945 macOS minutes (3 hangs x 315 minutes)$75.60
Lint and type checks ahead of the matrix3,395 matrix minutes removed, 1,800 gate minutes added$19.96

Matrix fail-fast. The setting defaults to true, and GitHub documents the behavior plainly: with fail-fast on, GitHub will "cancel all in-progress and queued jobs in the matrix if any job in the matrix fails" (workflow syntax, checked on 2026-08-13). A failing run bills 35 minutes with the setting on, 2 minutes for the failing leg plus 3 minutes each for 11 cancelled siblings, against 108 with it off, a difference of 73 minutes and $0.584 per failing run. Teams that set fail-fast: false to collect the full failure list are buying that list with those 73 minutes, which earns its cost on a nightly compatibility matrix and wastes it on a pull request matrix where the first red leg is enough. The fail-fast definition covers the cases where keeping every leg alive is worth paying for.

Job timeouts. timeout-minutes has a default of 360 (workflow syntax, checked on 2026-08-13), so a job that hangs on a network call holds its machine for six hours before anything stops it. On warp-macos-latest-arm64-6x at $0.08 per minute, one hang bills $28.80. Setting timeout-minutes: 45 on a job whose P90 duration is 20 minutes caps the same hang at $3.60. Set the value from the duration percentiles in the reports view rather than guessing, and set it on every job, since the default applies per job.

Cheap checks first. Lint and type checks finish in about 2 minutes on a 2 vCPU runner and catch a large share of first-attempt failures on most repositories. Putting them in their own job and pointing the matrix at it with needs means a broken lint run skips 108 minutes of test matrix instead of running it. The gate costs $0.008 on every run, including the 738 that pass, and removes $0.28 of matrix time on each of the 97 runs it catches.

Ordering cheap checks ahead of the expensive job

name: ci
on:
  pull_request:
    branches: [main]

jobs:
  checks:
    runs-on: warp-ubuntu-latest-x64-2x
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm run lint
      - run: npm run typecheck

  tests:
    needs: checks
    runs-on: warp-ubuntu-latest-x64-4x
    timeout-minutes: 25
    strategy:
      fail-fast: true
      max-parallel: 12
      matrix:
        shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm test -- --shard=${{ matrix.shard }}/12

The needs: checks line is what turns a lint failure into 12 skipped jobs. The explicit fail-fast: true restates the default so the next person to edit the matrix sees the decision. The two timeout-minutes values sit above the P90 duration of each job, which keeps a hang bounded without cancelling a slow but healthy run. The gate adds about 2 minutes of wall clock to every run that passes, and that latency is the real price of the pattern.

A month of failure and re-run waste

Baseline, with no gate and fail-fast: false on the matrix. Passing runs are excluded from both tables, since the levers do not change what a green run costs.

LineRunsMinutes eachMinutesCost
First-attempt failures16210817,496$139.97
Full re-runs of those failures11310812,204$97.63
Total27529,700$237.60

The same month with the gate in front and fail-fast on. The gate line for passing runs is included because the gate is the one lever that adds minutes to a green run.

LineRunsMinutes eachMinutesCost
Failures the gate catches972 gate194$0.78
Failures that reach the matrix652 gate + 35 matrix2,405$18.72
Full re-runs, gate included1132 gate + 108 matrix12,430$98.54
Gate on the 738 runs that pass73821,476$5.90
Total16,505$123.94

The monthly difference is $113.66, and the shape of the second table matters more than the total. Re-runs are now about 80 percent of what failure costs, because a re-run that goes green bills the full 108 minute matrix whatever the levers do. Cutting that line means fewer re-runs rather than shorter ones, which is a flakiness and retry-policy problem; what GitHub Actions re-run storms cost works through it.

The narrower re-run helps here too. GitHub allows re-running a whole run, all failed jobs, or one specific job for up to 30 days after the initial run (re-running workflows and jobs, checked on 2026-08-13), and re-running one 9 minute shard bills $0.072 against $0.864 for the full matrix.

Finding which jobs burn minutes on red

The reports documentation describes the two views that turn this into your own numbers. The Jobs section aggregates each unique repository, workflow, and job name combination with run count, success rate, and duration at P75 and P90, so sorting by success rate ascending and reading run count next to it ranks jobs by wasted attempts. The Billing section gives one row per job execution with execution time, billed time, and the runner and snapshot split, filterable by repository, runner label, and job name, and every table exports to CSV.

Duration P90 is also the number to set timeout-minutes from. A job with a P90 of 18 minutes and the default 360 minute cap carries 342 minutes of exposure on every hang.

What the bill never adds

The full rate list is on the pricing page.

Does a cancelled GitHub Actions job still cost money?

Yes. A cancelled job bills the minutes its machine ran before the cancellation landed, so a matrix leg cancelled at minute 3 of a 9 minute run bills 3 minutes rather than 9. The saving comes from the 6 minutes that never ran. See how a cancelled GitHub Actions job is billed for the same arithmetic on manual cancels and superseded pushes.

Do skipped jobs cost anything?

No. GitHub skips every job that lists a failed job in needs (workflow syntax, checked on 2026-08-13), and a skipped job never starts a machine, so it bills nothing. That is why a 2 minute lint gate in front of a 12 leg test matrix removes the whole matrix from the bill when lint is broken.

Is re-running only the failed jobs cheaper than re-running the whole workflow?

Yes. Re-running the 12 leg matrix in full bills 108 minutes, which is $0.864 at the $0.008 per minute rate on the pricing page. Re-running the single failed shard bills 9 minutes, or $0.072. GitHub exposes the narrower option as Re-run failed jobs in the run view and as gh run rerun RUN_ID --failed on the command line, for up to 30 days after the initial run (re-running workflows and jobs, checked on 2026-08-13). Habitual full re-runs are the pattern behind re-run storms.

Start with $10 in free credits

Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.