Run GitHub Actions Steps in Parallel With background

A terminal window showing the verbatim changelog entry for GitHub Actions parallel steps: background: true runs a step asynchronously and immediately continues to the next step
On this page

What used to force artificial serialization

Every step in a GitHub Actions job has always run strictly in order, one finishing before the next starts. That’s fine when steps genuinely depend on each other, but it forces unnecessary waiting when they don’t: three independent build tasks that don’t share state, or a background service (a test database, a mock API) that a later step needs running but doesn’t need to wait on immediately.

GitHub’s changelog, published 2026-06-25, adds four new step-level keywords to fix that:

background: true… runs a step asynchronously and immediately continues to the next step.”

wait/wait-all… pauses execution until one or more named background steps complete. wait can target one or more specific background steps, while wait-all pauses until all prior background steps have completed.”

cancel… gracefully terminates a background step when you no longer need it, enabling you to start long-running services with a background step.”

parallel… takes a group of steps and converts them to background steps with a wait after, enabling you to easily run multiple steps in parallel.”

None of these change how a job is triggered or how jobs relate to each other. They’re new keys inside an existing steps: block, not a new job or workflow structure.

Structural Comparison Matrix

Operational AspectPlain sequential steps (default)background + wait/wait-all/cancelparallel
Execution orderStrictly one after anotherA step starts, the job moves on immediatelyA whole step group starts together
Control over waitingN/A, waiting is implicit and totalExplicit: choose exactly which background step(s) to wait for, or none at allImplicit: the group is waited on automatically after it
Best fitSteps with a real order dependencyA background service another step needs, started early and stopped or waited on laterSeveral independent steps with no order dependency between them
Syntax overheadNoneAn id on the background step, plus a separate wait/cancel stepLowest, one parallel: block

Add background steps to a job

A common case: a test suite needs a real database running, but starting it doesn’t need to block installing dependencies. Give the background step an id, mark it background: true, and reference that id later:

.github/workflows/test.yml
jobs:
  integration-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - name: Start test database
        id: test-db
        background: true
        run: docker run -d --name test-db -p 5432:5432 postgres:16

      - name: Install dependencies
        run: npm ci

      - name: Wait for test database
        wait: test-db

      - name: Run integration tests
        run: npm run test:integration

      - name: Stop test database
        cancel: test-db

npm ci starts running the moment docker run is dispatched, not after it finishes, since the database step already handed control back. The wait: test-db step is where the job actually pauses until the container is up, right before the tests that need it.

Group independent steps with parallel

For steps that have no order dependency on each other at all, wrapping them in parallel avoids hand-managing ids and wait steps:

.github/workflows/build.yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

      - parallel:
          - name: Build frontend bundle
            run: npm run build:frontend
          - name: Build backend bundle
            run: npm run build:backend
          - name: Build docs site
            run: npm run build:docs

      - name: Package release
        run: npm run package

Exact syntax, verified against the changelog's own description

GitHub’s changelog describes the mechanics of background, wait, wait-all, cancel, and parallel in the exact terms quoted above, but doesn’t publish a full example workflow in the entry itself. The YAML shapes here match that described behavior, id-based background steps referenced by a later wait or cancel, and parallel grouping a set of steps with an implicit wait after, but weren’t run against a live workflow here. Confirm the exact indentation against GitHub’s workflow syntax reference before shipping it to a production pipeline.

Would this help this site’s own CI?

This site’s .github/workflows/ci.yml runs its build job’s steps in strict sequence: install, lint, format check, Astro check, unit tests, build, then Playwright install and end-to-end tests. Lint, the format check, and the Astro check don’t depend on each other, only on npm ci finishing first, which makes them a real candidate for a parallel block once this repo adopts a runner fleet new enough to support it. The unit tests and the build step still need to stay sequential, since the end-to-end tests run against the built output.

Confirmed version

Sourced from GitHub’s changelog entry announcing the new step keywords, published 2026-06-25. Browse more posts like this in the Dev Tools archive.

Frequently asked

Does background: true change how a job's overall status is calculated?

The changelog doesn't spell this out explicitly, and it wasn't independently reproduced here. Treat a background step's failure handling as unverified until you've tested it against your own workflow, and add an explicit wait or wait-all step before the job ends if you need its outcome to count toward the job's pass/fail result.

Can I use parallel and background/wait in the same job?

The changelog describes them as related but separate tools: parallel is sugar for grouping steps that all start together and are all waited on automatically, while background plus wait or cancel gives finer control, like doing other work between starting a step and waiting on it. Nothing in the changelog suggests they're mutually exclusive within one job.

Does this replace running independent jobs in parallel?

No. Separate jobs in the same workflow already run in parallel by default unless a needs: dependency chains them. This feature is about parallelism inside a single job's steps, which previously had no option but strict sequential execution.

Emitted as FAQPage JSON-LD from the same frontmatter — one source, no duplicated prose.

Recent posts

Full-text search via Pagefind · ↑↓ to navigate · ↵ to open