GitLab Runner Concurrency Limits - config.toml concurrent / limit
How many jobs a runner host runs in parallel is governed by concurrent (global) and per-runner limit in config.toml. Set too low, jobs queue; set too high, the host is overloaded.
What this error means
Jobs sit in pending even though the runner is online and not busy, or the host is overwhelmed running too many jobs at once. The bottleneck is the concurrency configuration, not job tags.
# config.toml - global cap is 1, so only one job runs at a time:
concurrent = 1
[[runners]]
name = "docker-runner"
limit = 0 # 0 = unlimited for this runner, but global concurrent still caps itCommon causes
Global concurrent set too low
The top-level concurrent value caps total simultaneous jobs across all runners on the host. A default of 1 serializes everything regardless of per-runner limits.
Per-runner limit too low
Each [[runners]] entry has a limit. A low value throttles that runner even when global concurrent allows more.
Concurrency set above host capacity
Too-high values let more jobs start than the CPU/memory can handle, causing thrashing, OOM kills, and slow jobs.
How to fix it
Tune global and per-runner concurrency
Set concurrent to the total parallel jobs the host can handle and limit per runner accordingly.
concurrent = 8
[[runners]]
name = "docker-runner"
limit = 8
[runners.docker]
# ...Right-size to host resources
- Estimate per-job CPU/memory and divide host capacity to pick a safe
concurrent. - Restart the runner after editing
config.tomlso changes take effect. - Watch host load; lower the value if you see OOM kills or thrashing.
How to prevent it
- Size
concurrentfrom real per-job resource usage, not guesswork. - Keep per-runner
limitconsistent with globalconcurrent. - Monitor host CPU/memory and adjust concurrency to avoid overload.