Mutation testing is expensive because each mutant needs a test run, and the number of mutants scales with the size of the code you mutate. The CircleCI introduction to mutation testing describes the loop plainly: the tool generates one mutant per applied operator at each eligible location, then runs the suite against each mutant and classifies the result. Every one of those runs consumes the same machine resources as a normal test execution.
So the arithmetic has three inputs. The first is the mutation scope: how many functions or files you hand to the tool. The second is the mutant density, or how many mutants the tool generates per function. The third is the average time a test run takes once a mutant is active. Multiply them and you have raw test-execution time, which you then divide by the number of parallel workers your CI budget permits.
A useful unit of account is the function-minute: how many CI minutes one function costs when fully mutated. If a service has 240 functions that average 6 mutants each, you have 1,440 mutants. If a full test pass takes 40 seconds per mutant and you run 8 workers, wall-clock time is 1,440 × 40 / 8 = 7,200 seconds, or 2 hours. That single line of arithmetic tells you more about feasibility than any benchmark you will read online, because it uses your numbers.
Two properties make the raw number worse than it looks. First, mutation testing needs a green baseline before it starts, and every tool performs a dry run to discover tests and per-test coverage; the StrykerJS incremental documentation states that the dry run remains required even in incremental mode. Second, static mutants (mutants in code that executes once at startup rather than during tests) cannot be activated per test and may need a fresh environment per mutant. The Stryker team documents this as a "big performance impact" and notes that Stryker4s simply ignores static mutants by default, while StrykerJS offers an --ignoreStatic flag (static mutants). Ignoring them is usually the correct budgeting decision.
Here is a template spreadsheet row you can reproduce for each module:
| Input | How to get it | Example |
|---|---|---|
| Mutated functions | Count functions in scope | 240 |
| Mutants per function | One trial run on a sample | 6 |
| Total mutants | Functions × mutants per function | 1,440 |
| Seconds per mutant | Time a filtered test pass | 40 |
| Parallel workers | CI concurrency cap | 8 |
| Wall-clock minutes | Mutants × seconds / workers / 60 | 120 |
| Dry-run overhead | Measured baseline pass | 4 |
| Realistic budget | Wall-clock plus 25% headroom | 155 |
The headroom matters. Survivors that time out, mutants that hang, and runners that restart all consume minutes you did not model.



