Skip to content
Latchkey
Documentation menu

Run your first job on a Latchkey runner

Switch a GitHub Actions job to a managed runner by changing one line of YAML, watch it get picked up, and verify it in the dashboard.

Before you start

The one-line change#

Before: GitHub-hosted

yaml
jobs:
  test:
    runs-on: ubuntu-latest

After: Latchkey

yaml
jobs:
  test:
    runs-on: latchkey-small

You never have to type a label from memory: every row of the Your runners table on the Runners page has a Copy CI snippet action, and each runner's detail drawer includes a Use in CI card with the label and a copyable snippet.

Both label forms route identically; use whichever your conventions prefer:

.github/workflows/ci.yml
name: CI
on: [push]

jobs:
  test:
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
      - run: npm ci
      - run: npm test
.github/workflows/ci.yml
name: CI
on: [push]

jobs:
  test:
    runs-on: [self-hosted, latchkey-small]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
      - run: npm ci
      - run: npm test

Sizes are chosen per job, not per workflow: give the heavy job more machine and keep everything else on latchkey-small. Moving up a size doubles the per-minute rate, so it pays for itself when it at least halves the job's duration; see the sizing guidance.

.github/workflows/build.yml
jobs:
  heavy-build:
    runs-on: latchkey-large   # 8 vCPU / 32 GB for the heavy job
  quick-lint:
    runs-on: latchkey-small   # keep cheap jobs on small

runs-on accepts expressions, so a matrix can route each leg to the size it needs: light legs stay on the small rate while only the heavy leg pays for the bigger machine.

.github/workflows/ci.yml
jobs:
  test:
    strategy:
      matrix:
        include:
          - suite: unit
            runner: latchkey-small
          - suite: integration
            runner: latchkey-large
    runs-on: ${{ matrix.runner }}
    steps:
      - uses: actions/checkout@v4
      - run: npm run test:${{ matrix.suite }}

Or generate it#

Build your runs-on line

Paste this into any workflow under .github/workflows/. Everything else in the job stays unchanged.

Ship it and verify#

Commit and trigger the workflow

Push the change or trigger the workflow manually. On GitHub, the job shows as queued until a runner picks it up: seconds if a warm runner is available, about 10 seconds for a fresh runner (GitHub-hosted typically takes 30-60 seconds), with zero queue time either way.

Verify where it ran

In the GitHub run view, the job's runner name confirms a Latchkey machine took it rather than a GitHub-hosted one. Because every runner is destroyed after one job, do not expect a familiar name from run to run: a fresh machine takes each job, which is the ephemeral design working as intended.

Find the minutes

In the Latchkey dashboard, the Runners page shows the run in your fleet activity, and its minutes appear against your free tier. Over time the same numbers surface in two more places: the billing modal (free-tier progress, billable minutes, estimated cost so far) and the Cost Analysis page, which tracks Latchkey runner spend alongside your GitHub spend. Details in Runner usage and free minutes.

If the job just sits in "queued"#

A job that never gets picked up is the standard symptom for every routing problem: the repository is not monitored, managed runners are not enabled, the label has a typo, a custom runner's image is still building, or runner launches are blocked by billing. There is no explicit error in the GitHub UI in these cases. Walk through Troubleshooting: job stays queued to pin down which one it is.

Common questions#

Do my GitHub-hosted labels keep working?

Yes. ubuntu-latest and friends keep working side by side; installing Latchkey changes nothing about them. You can migrate one job at a time and leave the rest untouched for as long as you like.

Can I mix Latchkey and GitHub-hosted runners in one workflow?

Yes, freely. runs-on is decided per job, so a workflow can run its Linux jobs on latchkey-* labels while jobs that need GPU, Windows, macOS, or arm64 hosts stay on GitHub-hosted or other runners.

Do I need to change anything besides runs-on?

For most workflows, no. The runner image is designed to match or exceed GitHub-hosted runners, and actions/setup-* steps resolve from the same toolcache layout, so the rest of the job stays as it is.

What does this first run cost me?

Minutes are billed per minute, rounded up per job, at the size's rate, and every plan includes free minutes each month. Unless you have already used up your free tier, a short test run costs nothing. See Runner usage and free minutes.