GitHub Actions concurrency deadlock between deploy jobs
A concurrency group serializes runs, but if a dependent job needs another job that is itself queued behind the same group, the chain can stall. Misusing cancel-in-progress across coupled deploy jobs produces an apparent deadlock.
What this error means
Two deploy jobs sit pending indefinitely, each effectively waiting for the other because they share a concurrency group with a dependency between them.
github-actions
Waiting for a deployment slot in concurrency group "deploy-production"
(job "promote" pending behind "deploy", which needs "promote")Common causes
Coupled jobs share one concurrency group
Jobs linked by needs are placed in the same group, so one cannot start until the other releases the slot it is also waiting on.
cancel-in-progress canceling the wrong run
cancel-in-progress cancels an in-flight run that a dependent job relies on, leaving the pipeline stuck.
How to fix it
Separate the concurrency scope
- Put serialization at the workflow level for a single deploy pipeline, not on individual coupled jobs.
- Give independent pipelines distinct concurrency group keys.
- Use cancel-in-progress only where superseding an older run is actually safe.
.github/workflows/deploy.yml
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: falseHow to prevent it
- Scope concurrency to a whole pipeline rather than to interdependent jobs.
- On Latchkey managed runners, jobs stuck purely on transient slot contention are retried automatically; a true config deadlock still needs the scope fix above.
Related guides
GitHub Actions "deployment protection rule timed out"Fix the GitHub Actions error where a custom deployment protection rule timed out waiting for an external appr…
GitHub Actions "Failed to create deployment" status errorFix the GitHub Actions "Failed to create deployment" error - the deployments API call failed due to permissio…
GitHub Actions "workflow_run did not trigger" (default branch only)Fix a GitHub Actions workflow_run that never fires because the triggered workflow file only exists/runs on th…