perf(test): cap vitest fork pool at 4 workers (#828)

Vitest's fork pool default scales with availableParallelism, which
on machines with many cores spawns dozens of fresh workers. Each
worker dynamic-imports the full Express stack (TypeScript transform
+ DB constructor + every migration) and saturates CPU on cold start.
Most of the previous suite wall time was spent waiting on this
contention rather than running tests.

Cap concurrency at 4 workers via the new top-level maxWorkers /
minWorkers options (Vitest 4 unified the previous
poolOptions.forks.maxForks under maxWorkers across pool types).
Local backend wall time drops from ~93 s to ~32-60 s on typical
runs. The pre-existing pre-cap fork-contention flakes (rate
limiting, metrics-routes, fleet integration) clear consistently
on the warm path; the remaining variance is environmental
(background processes, antivirus on Windows) and is what it was
before this change minus the contention floor.

testTimeout (30 s) and hookTimeout (45 s) stay generous so the
stress path in database-metrics and the HTTP integration suites
still cover their cold-start envelope on slow runners.
This commit is contained in:
Anso
2026-04-28 10:08:26 -04:00
committed by GitHub
parent f4338c9d6b
commit 65f43b8032
+9 -1
View File
@@ -8,11 +8,19 @@ export default defineConfig({
exclude: ['dist/**', 'node_modules/**'],
// Each test file gets its own worker so singletons are fresh between files.
pool: 'forks',
// Cap concurrency: each worker dynamic-imports the full Express stack
// (TypeScript transform + DB init + every migration), so an uncapped
// fork pool that scales with availableParallelism saturates CPU and
// the suite spends most of its wall time waiting on cold-start
// contention. Four parallel workers is a sweet spot on both CI
// runners and laptops.
maxWorkers: 4,
minWorkers: 1,
// Timeout generous for DB init and HTTP calls.
testTimeout: 30_000,
// Every test file dynamic-imports the full Express stack; each fork pays
// TypeScript transformation cost and can take tens of seconds under
// CPU contention when all 64 fork workers run at once.
// CPU contention.
hookTimeout: 45_000,
// Sequential within each file (DB state is shared per file).
sequence: { concurrent: false },