Diagnosing Slow Vitest Runs: Verifying Parallel Execution Settings
When a Vitest suite takes longer than expected, the cause is often a configuration that silently limits parallelism. This guide walks through checking concurrency, file parallelism, and pool settings, then applying targeted fixes.
08 Jun 2026, 21:52 UTC

Recognizable Condition
A Vitest suite that once finished quickly begins taking far longer than expected, especially after the number of test files grows. The slowdown may appear when moving from a small local run to a larger CI job, or after a dependency upgrade changes default worker behavior. Individual tests remain fast, yet the total wall-clock time balloons because files are executing one after another instead of sharing available CPU cores.
The useful takeaway: Vitest does not always run in parallel by default in every configuration. A single overlooked key in vitest.config.ts can silently cap concurrency, disable file-level parallelism, or restrict the worker pool. Before profiling individual tests, verify that the runner is actually using the parallelism you expect.
Common Causes and Diagnostic Signals
| Cause | Diagnostic Signal |
|---|---|
| Concurrency capped at 1 or a very low value | Config shows maxConcurrency: 1 or similar; startup log reports a low active test count. |
| File parallelism disabled | Test files run strictly one at a time even when the machine has idle cores. |
| Pool or worker limits set too low | Pool options such as thread maximums restrict active workers below the available CPU count. |
| Watch mode or a sequential override active | Tests run serially inside files; a plugin or environment variable forces sequential execution. |
| I/O-bound bottleneck | CPU stays mostly idle while tests wait on network, disk, or database calls. |
Ordered Checks
- Inspect the test configuration file. Open
vitest.config.ts(orvitest.config.js) and look for keys under thetestobject that control parallelism:maxConcurrency,fileParallelism,pool, andpoolOptions. A value of1for concurrency orfalsefor file parallelism forces serial execution. - Verify the execution mode. Run
npx vitest runin a terminal or CI job. Watch mode (vitestwithoutrun) is optimized for re-running changed files and may not allocate workers the same way. Confirm your pipeline uses theruncommand. - Check pool and worker settings. If
test.poolis set to'threads'or'forks', inspectpoolOptionsformaxThreads,minThreads, or analogous limits. A low maximum caps parallelism regardless of how many cores the machine has. - Review plugins and environment overrides. Some setups add plugins or environment variables that force sequential behavior. Temporarily disable recently added test plugins to see if parallelism returns.
Fixes Tied to Findings
- If concurrency is capped: Raise
test.maxConcurrencyfrom1to a higher value such as10. This controls how many tests inside a single file may run at once. Restart the Vitest process; config changes are not hot-reloaded. - If file parallelism is disabled: Set
test.fileParallelism: trueto allow multiple test files to run simultaneously across workers. - If pool limits are restrictive: Increase
poolOptions.threads.maxThreads(or the equivalent for your pool) to match your available CPU cores. Start with a conservative value and increase while monitoring memory. - If a plugin forces serial runs: Remove or disable the plugin, then re-run the suite. If the plugin is required, check whether it exposes an option to relax sequential enforcement.
Example configuration change
In vitest.config.ts, change:
export default defineConfig({
test: {
maxConcurrency: 1,
fileParallelism: false,
},
});
to:
export default defineConfig({
test: {
maxConcurrency: 10,
fileParallelism: true,
pool: 'threads',
poolOptions: {
threads: {
maxThreads: 8,
},
},
},
});
Run from your project root with npx vitest run --verbose. No elevated permissions are required. Compare the total duration reported at the end of the run before and after the change. Look for startup log lines that report the active worker or concurrency level; if the log does not reflect the new values, the keys may be ignored by your installed Vitest version.
Escalation Criteria
If the suite remains slow after raising concurrency and enabling file parallelism, the bottleneck likely lies elsewhere:
- Oversized test files: A single file with hundreds of tests cannot be parallelized internally beyond
maxConcurrency. Split large files into smaller units. - Heavy async setup: Long
beforeAllorbeforeEachhooks that perform network or database calls serialize the suite regardless of worker count. Mock external services or move setup to a global fixture where possible. - Resource saturation: If raising workers causes flaky failures, memory exhaustion, or CI timeouts, reduce
maxThreadsand profile memory usage. Parallelism helps only when the workload is CPU-bound; I/O-heavy tests may contend for the same external resource.
If the problem persists across multiple Vitest versions after these adjustments, collect your vitest.config.ts, the exact vitest version from package.json, and a verbose run log, then open an issue in the Vitest repository.
Limitations and Practical Verification
Configuration keys and defaults have changed across Vitest major versions. A key that works in one release may be renamed, deprecated, or ignored in another. Before relying on any setting, confirm it against the reference documentation for the exact version in your package.json.
To verify the change took effect, run npx vitest run --verbose from the project root. The command prints per-file results and a final duration summary. If the duration does not improve and the startup log does not mention your configured worker or concurrency level, treat the setting as unapplied and re-check the key name for your version.
As a rollback, revert the edited values in vitest.config.ts to their previous state and re-run the suite. Because this change modifies project configuration, keep the original file in version control so you can restore it cleanly.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.