---
title: "Run independent test packages concurrently"
description: "Let independent packages or test environments run at the same time instead of invoking each one serially."
url: https://starsling.dev/ci-playbooks/techniques/parallel-test-packages
canonicalUrl: https://starsling.dev/ci-playbooks/techniques/parallel-test-packages
---

# Run independent test packages concurrently

Let independent packages or test environments run at the same time instead of invoking each one serially.

## How to choose an approach

Compare the examples by repository setup, prerequisites, and risks before adopting one. Each company implemented this in its own environment; measure each change against your own baseline.

- **[Anthropic](https://starsling.dev/ci-playbooks/anthropic#parallel-crates)**: Use it when A serial test driver runs independent packages, crates or modules one after another on a multi-core runner. Check before adopting: Each process keeps its own log, and the job reports every failing package.
- **[Spotify](https://starsling.dev/ci-playbooks/spotify#pytest-xdist)**: Use it when One test environment takes most of the CI time and runs in a single process on a multi-core runner. Check before adopting: Tests that share files, ports or global state need per-worker isolation; grouping by file keeps a file's tests together.
- **[Uber](https://starsling.dev/ci-playbooks/uber#parallel-package-tests)**: Use it when A shell loop runs independent packages one at a time even though the language test runner schedules packages in parallel. Check before adopting: Remove shared-resource dependencies first, keep special-case tests, race settings and combined coverage, and measure CPU and memory at several concurrency levels.

## Apply this technique

````text
Evaluate and apply this CI technique to my repository: Run independent test packages concurrently.

Let independent packages or test environments run at the same time instead of invoking each one serially.

Read the technique and its source-backed company examples: https://starsling.dev/ci-playbooks/techniques/parallel-test-packages.md

Inspect this repository’s CI workflows, build and test commands, dependencies, and recent run timings. Identify where this technique applies and explain the expected benefit using this repository’s evidence.
Measure a baseline from recent comparable runs: elapsed time, queue time, runner minutes and failures where available. If data is unavailable, say what cannot be measured.
Compare relevant company approaches, checking prerequisites, platform differences and tradeoffs. Rank applicable options by evidence, fit and measurable opportunity; do not present company results as predictions for this repo.
Recommend the smallest safe change, show what checks and fallback paths remain, and ASK ME WHICH CHANGE TO APPROVE BEFORE EDITING ANY FILES.
Only after approval, work on a new feature branch, make one reversible change, and open a reviewable pull request. Never merge or push to a default or protected branch.
Keep required checks, test coverage, deployment and release behavior intact. Validate the change and compare equivalent runs where possible; report limitations and what should be monitored after merge.
````

## How companies used this technique

Read what each company changed and follow the original sources.

### Anthropic: Run independent test packages concurrently

Bun's Miri script builds every crate once, then runs one cargo miri test per crate, as many at a time as the runner has cores, longest crates first. It waits for all of them and exits nonzero if any crate reports an error.

Evidence: Estimate

The PR expects the Miri job to go from about 14.5 minutes to about 4 to 5 minutes (estimate), with the concurrent crates and a smaller Miri-sized tracker test together. ([Source](https://github.com/oven-sh/bun/pull/39218))

Use it when: A serial test driver runs independent packages, crates or modules one after another on a multi-core runner.

Before applying it: Each process keeps its own log, and the job reports every failing package.

[Read more in the Anthropic playbook](https://starsling.dev/ci-playbooks/anthropic#parallel-crates)

[Primary source](https://github.com/oven-sh/bun/pull/39218)

### Spotify: Run the slowest test environment in parallel workers

This is a community contribution to Spotify's luigi project. Luigi's core test environment took about five minutes while the others took about a minute or less. The change adds pytest-xdist and runs the core tests with -n auto --dist=loadfile, which spreads test files across one worker per CPU and keeps each file's tests on one worker.

Evidence: Source PR/commit evidence

The author reports the core workflows running in 2 to 4 minutes, 1 to 2 minutes faster. ([Source](https://github.com/spotify/luigi/pull/3398))

Use it when: One test environment takes most of the CI time and runs in a single process on a multi-core runner.

Before applying it: Tests that share files, ports or global state need per-worker isolation; grouping by file keeps a file's tests together.

[Read more in the Spotify playbook](https://starsling.dev/ci-playbooks/spotify#pytest-xdist)

[Primary source](https://github.com/spotify/luigi/pull/3398)

### Uber: Let the test runner schedule independent packages

After isolating its unit suite, Cadence replaced a shell loop that ran go test once per package with one invocation over the package list, so Go schedules independent packages concurrently and writes one coverage profile. OPT88's serial-suite diagnosis is adapted.

Evidence: Source PR/commit evidence

The PR reports unit and integration test runs and builds on the dependency isolation in cadence-workflow/cadence#6800. ([Source](https://github.com/cadence-workflow/cadence/pull/6801))

Use it when: A shell loop runs independent packages one at a time even though the language test runner schedules packages in parallel.

Before applying it: Remove shared-resource dependencies first, keep special-case tests, race settings and combined coverage, and measure CPU and memory at several concurrency levels.

[Read more in the Uber playbook](https://starsling.dev/ci-playbooks/uber#parallel-package-tests)

[Primary source](https://github.com/cadence-workflow/cadence/pull/6801)

## CI optimization is continuous work.

Apply this technique yourself, or use StarSling Runners for faster GitHub Actions and optional agent-driven optimization PRs, which teams on eligible paid plans can turn on.

[Get self-improving CI](https://starsling.dev/products/runners)

## Related techniques

### [Build the test database once for all workers](https://starsling.dev/ci-playbooks/techniques/coordinate-test-setup)

Have one parallel worker apply the schema while the others wait for it, so more workers stop repeating the same setup.

1 implementation · 1 company (Ramp)

### [Isolate state before running tests in parallel](https://starsling.dev/ci-playbooks/techniques/isolated-parallel-tests)

Give concurrent tests independent databases, services, or fixtures so they can share runner capacity without interfering with each other.

5 implementations · 5 companies (DoorDash, Ramp, Shopify, Stripe, Uber)

### [Match test concurrency to the runner](https://starsling.dev/ci-playbooks/techniques/tune-test-workers)

Measure worker counts against available CPU and memory. More workers help only while the runner has capacity.

4 implementations · 4 companies (Anthropic, Mastra, OpenAI, Stripe)

## Company Playbooks

### [Anthropic](https://starsling.dev/ci-playbooks/anthropic)

Run only affected tests

### [DoorDash](https://starsling.dev/ci-playbooks/doordash)

Run build and test in parallel, sharded across CI agents

### [Linear](https://starsling.dev/ci-playbooks/linear)

Benchmark the same job on faster hardware

### [Mastra](https://starsling.dev/ci-playbooks/mastra)

StarSling runners for the slowest test workflow

### [OpenAI](https://starsling.dev/ci-playbooks/openai)

Rank CI fixes by the minutes they save

### [Ramp](https://starsling.dev/ci-playbooks/ramp)

Move a CPU-bound test suite to a faster CPU

### [Shopify](https://starsling.dev/ci-playbooks/shopify)

Let an agent iterate against one CI metric

### [Spotify](https://starsling.dev/ci-playbooks/spotify)

Build arm64 on native arm64 runners

### [Stripe](https://starsling.dev/ci-playbooks/stripe)

Run only the tests a change can reach

### [Uber](https://starsling.dev/ci-playbooks/uber)

Build the merge-queue speculations most likely to be needed

## Related guides

Implementation guides for this technique.

### [Shard tests across parallel jobs](https://starsling.dev/best-practices/github-actions/shard-tests)

Split a long suite with a matrix and your test framework’s sharding support.

### [Cut repeated test setup](https://starsling.dev/best-practices/github-actions/cut-repeated-test-setup)

Move shared fixture work out of individual test cases and keep necessary cleanup.

### [Diagnose slow tests in CI](https://starsling.dev/github-actions/problems/slow-tests)

Check common causes in order and confirm each with workflow evidence.

### [Optimize Playwright tests](https://starsling.dev/github-actions/optimizations/optimize-playwright)

Choose trace and video retention and install the browsers your suite uses.

### [Make Vitest run mode explicit](https://starsling.dev/github-actions/optimizations/optimize-vitest)

Pin run mode to the test command and bound the job with a timeout.

### [Parallelize independent jobs](https://starsling.dev/github-actions/optimizations/parallelize-independent-jobs)

Run independent validation lanes concurrently and keep genuine job dependencies.
