Jobs, Steps, and Runners Explained
Jobs, steps, and runners are the three nested units that decide what runs, in what order, and on which machine.
Jobs, steps, and runners are easy to confuse but behave very differently - especially around parallelism and isolation. This lesson nails down the distinctions so your workflows do what you expect.
Steps run in sequence
A step is the smallest unit: a single command or action. Steps inside a job run in order, top to bottom, on the same runner, sharing the same filesystem and environment. If a step fails, the remaining steps in that job are skipped by default. Steps are how you express "do this, then this, then this."
Jobs run in parallel
A job is a group of steps that runs on its own runner. Importantly, jobs in a workflow run in parallel by default, each on a separate, isolated machine. This is great for speed - you can lint, test, and build simultaneously - but it means jobs do not share files unless you use artifacts or declare dependencies with needs.
Runners are the machines
A runner is the virtual machine or container that executes a job. You pick one with runs-on. GitHub-hosted options include ubuntu-latest, windows-latest, and macos-latest. Every job starts on a clean runner, which guarantees reproducibility but also means nothing persists between jobs automatically.
jobs:
lint:
runs-on: ubuntu-latest # one runner
steps:
- uses: actions/checkout@v4
- run: npm run lint
test:
runs-on: ubuntu-latest # a separate runner, runs in parallel
steps:
- uses: actions/checkout@v4
- run: npm testChoosing a runner
- Match the OS to your project -
ubuntu-latestis the cheapest and fastest default. - Use
macos-latestonly when you need it (e.g. iOS builds); it costs more. - For lower cost and automatic retry of transient infrastructure failures, managed runner platforms like Latchkey are a drop-in alternative.
Key takeaways
- Steps run sequentially on one shared runner; a failure stops the job.
- Jobs run in parallel on separate, isolated runners by default.
- Runners are fresh machines chosen with
runs-on; nothing persists between jobs automatically.