Documentation menu
Getting started
Dashboard & analytics
- Dashboard at a glance
- Cost analysis
- Pipeline performance
- Optimization insights
- Knowledge Base
- Connect your AI agent
Managed runners
- Runners overview
- Run your first job
- Migrate from GitHub-hosted
- The Runners page
- Custom runners (AI Scan)
- Self-healing
- Runner image & software
- Provisioning & warm pools
- Limits & concurrency
Caching
Team & notifications
Billing & plans
Help
How provisioning works
What happens between a job queueing on GitHub and a runner picking it up: warm pools, cold starts with just-in-time registration, the concurrency ceiling, and why a job might wait.
When GitHub queues a job with a latchkey-* label, a webhook tells Latchkey immediately, and Latchkey makes one decision: hand the job to a runner that is already warm, or launch a fresh machine for it. You never see that decision, but it is the difference between a pickup in a few seconds and one in about ten, and it explains most of what this page covers.
latchkey-* labelWarm pickup vs cold start#
A warm pickup means a pre-provisioned runner was already online for your workspace: the job is handed straight to it and starts within a few seconds. A cold start means no warm runner fit, so a fresh machine boots just for that job, registers with GitHub using a just-in-time, single-use configuration, and is running your steps in about 10 seconds. Both paths end identically: the runner takes exactly one job and the machine is terminated when the job finishes.
Warm pools#
| Plan | Warm pool |
|---|---|
| Developer | One warm latchkey-small runner plus parked capacity |
| Launch | The same baseline: one warm runner plus parked capacity |
| Scale | The same baseline: one warm runner plus parked capacity |
Every plan gets the same warm baseline today, and it covers latchkey-small only: one always-on warm runner backed by parked machines that resume in seconds. Anything beyond that, and any job asking for a larger size, cold-starts in about 10 seconds. Warm capacity costs you nothing while it idles; billing is per job minute, and an idle warm runner is not running a job.
Ephemeral, always#
Provisioning never reuses a machine. Warm or cold, a runner takes exactly one job and is terminated afterward, along with its disk, which is why runner names in the GitHub run view change on every run and why anything a job writes to local disk is gone when the job ends. The security side of this design, just-in-time credentials, private networking, and encrypted single-use disks, is covered in Security architecture.
Concurrency#
A workspace runs up to 20 concurrently busy runners by default, and only busy runners count: idle warm runners never consume a slot, so warm capacity does not compete with your real jobs. When a burst needs more than 20 at once, the overflow jobs stay queued until a slot frees, then start on their own; nothing errors and nothing is lost. If your peaks queue regularly, higher limits are available, contact support.
Hard boundaries#
- Jobs are capped at 4 hours; the machine is terminated at 4 hours even if the job is still running.
- Runners are Ubuntu 24.04 LTS on x86_64 only: no Windows, macOS, arm64, or GPU hosts.
- Runners run in AWS us-east-1.
The full table, including disk sizes and per-plan custom configuration counts, is in Limits and concurrency.
Why a job might sit in queued#
When provisioning cannot or will not launch a runner, there is no error on GitHub's side; the job just waits. That is by design: jobs targeting latchkey-* labels stay queued on GitHub rather than erroring. The usual causes:
- A label typo: no configuration matches the label, so nothing ever picks the job up.
- The repository is not monitored, or the runner configuration is disabled.
- A billing or trial block: an expired trial, a lapsed subscription, or an exhausted free tier on a card-less trial. A "Managed runner blocked" notification fires when this happens, at most once per day.
- A custom runner's image is still building; jobs targeting its label wait until the build completes.
- The workspace is at its 20-busy-runner ceiling; the job starts as soon as a slot frees.
The symptom-by-symptom walkthrough, with how to confirm each cause, is in Troubleshooting.