Jest Slow? How to Speed Up Jest Tests
If Jest is slow, the usual culprits are a slow TypeScript transform, too many or too few workers, heavy module imports repeated in every test file, and a single CI job running everything. This guide shows how to speed up Jest tests, including how to speed up Jest tests with TypeScript and how Jest test sharding works with --shard. It is part of the slow e2e tests cluster, which also covers slow integration tests.
Find out why Jest is slow
Start with numbers.
npx jest --verbose # per-test time
npx jest --listTests | wc -l # how many files
npx jest --logHeapUsage # memory per test file
npx jest --detectOpenHandles # why it will not exit
Jest prints a slow-test warning for individual tests over five seconds by default. Look for two patterns: a few very slow files (fix those), or a large fixed cost per file (module loading and transform), which hits every file.
Fix the transform first
Type-checking transforms are the biggest cause for TypeScript projects. ts-jest type-checks each file by default. Either turn that off and type-check once with tsc --noEmit in a separate job, or switch to a transpile-only transformer such as @swc/jest:
// jest.config.js
module.exports = {
transform: {
"^.+\\.(t|j)sx?$": ["@swc/jest"],
},
};
With ts-jest, set isolatedModules: true (or diagnostics: false) to skip type-checking per file. Keep type-checking in CI as its own parallel job, so correctness is unchanged.
Set workers deliberately
Jest runs test files in parallel worker processes. By default it uses cores minus one. On a 2-vCPU CI runner that is one worker, so the suite is effectively serial. Set it explicitly:
npx jest --maxWorkers=100% # all cores, good on a CI runner dedicated to tests
npx jest --maxWorkers=50% # leaves room for a dev machine
npx jest --runInBand # one process; can be faster for tiny suites
For very small suites --runInBand avoids worker start-up. For big suites the right number is close to the core count. Memory matters too: if workers are killed, lower the count or raise the runner's RAM.
Cut per-file overhead
- Barrel files: importing a package's
index.tscan load hundreds of modules. Import from the specific file in tests. - Heavy setup: move expensive setup to
globalSetup(runs once) rather thansetupFilesAfterEnv(which runs before every test file). - Test environment:
jsdomis slower to create thannode. Use@jest-environment nodefor tests that do not touch the DOM. - Cache: Jest's transform cache is on by default. In CI, cache the
cacheDirectory(npx jest --showConfig | grep cacheDirectory) withactions/cache, keyed on the lockfile and config. See GitHub Actions caching. - Changed files only:
--onlyChangedor--changedSince=origin/mainruns tests related to changes. Good for PR checks; keep a full run on main.
Jest test sharding
Jest has built-in sharding since version 28. --shard=index/count runs one slice of the test files:
npx jest --shard=1/4
npx jest --shard=2/4
In GitHub Actions run one slice per matrix job:
jobs:
jest:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22, cache: npm }
- run: npm ci
- run: npx jest --ci --maxWorkers=100% --shard=${{ matrix.shard }}/4
Sharding is by test file, not by duration, so one shard can be slower if it receives the big files. If shards are uneven, split large files or use a duration-based splitter. Coverage needs merging; the test sharding guide shows how, and the planner estimates the number of shards.
Slow integration tests inside Jest
If tests hit a database, make them cheap. Create the schema once in globalSetup, give each worker its own database (JEST_WORKER_ID is set in each worker), and wrap each test in a transaction that rolls back. Avoid sleep; use jest.useFakeTimers() for time-based logic.
When Jest itself is the bottleneck
Some teams move to Vitest for faster start-up; see Vitest slow for what to check there, since it has its own slow paths. Migration is a project, not a flag, so fix the transform and workers first.
Give CI more CPU
Test suites with many files scale with cores. If workers are limited by a 2-vCPU runner, compare options in faster GitHub Actions runners. compiler.dev was faster than GitHub's 2-core runner on 15 of 19 benchmarked stacks, by 1.1 to 3 times, and comparison mode measures your own jobs. The wider picture is in the slow CI hub.
FAQ
How do I speed up Jest tests?
Switch to a transpile-only transform, set --maxWorkers for your machine, cut per-file imports, cache the Jest cache directory in CI and shard across jobs with --shard.
How do I speed up Jest tests with TypeScript?
Use @swc/jest or ts-jest with isolatedModules, and run tsc --noEmit as a separate parallel job.
Does Jest support test sharding?
Yes, from Jest 28: jest --shard=1/3. It splits by file, so balance may be uneven.
Why is Jest slower in CI than locally?
Fewer cores (so fewer workers), an empty transform cache and often a type-checking transform. Fix each in turn.
Made by compiler.dev. Free tools · Pricing