Your CI Is Running Tests on Old Code: How to Auto-Cancel GitHub Actions
Table of Contents
- The Fix: Three Lines of YAML
- What This Does
- Why the
groupKey Looks Like That - Time = Money
- When You Shouldn’t Use This
- Copy-Paste Template
The Fix: Three Lines of YAML
Add this to the top of your workflow file, right after the on: section:
name: Tests
on:
pull_request:
# Add these 3 lines:
concurrency:
group: ${ { github.workflow } } -${ { github.event.pull_request.number || github.ref } }
cancel-in-progress: true
jobs:
test:
# ... your existing jobs
What This Does
The concurrency configuration creates a group for your workflow runs. When a new commit arrives:
- GitHub checks if another run is already in progress for this PR
- If yes, it cancels the old run
- Only the most recent run continues

Why the group Key Looks Like That
group: ${ { github.workflow } } -${ { github.event.pull_request.number || github.ref } }
This creates a unique group for each PR by combining:
- The workflow name (so different workflows don’t interfere with each other)
- The PR number (or branch name as a fallback for non-PR triggers)
Time = Money
Before adding this, I could have 3-4 test runs executing in parallel during active development. Each run took ~10-15 minutes. That’s ~45 minutes of Actions time where only the last 15 minutes actually mattered.
After adding concurrency cancelation: only one run at a time. Immediate savings.
When You Shouldn’t Use This
There are a few cases where you might not want automatic cancelation:
- Deploy workflows: If you’re deploying to production, you probably want every commit to deploy sequentially, not cancel previous deploys
- Scheduled workflows: Nightly jobs or cron tasks should run independently
- Workflows that create artifacts you need: If each run produces something you want to keep, cancelation might end up removing a needed artifact in the process.
Copy-Paste Template
name: Tests
on:
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Run tests
uses: actions/checkout@v4
run: npm test
This is the easiest GitHub Actions optimization you can make. Three lines of configuration, zero complexity, immediate savings on your GitHub Actions bill.