Performance
This page summarizes a benchmark baseline
for @fobx/core versus MobX.
These numbers are a point-in-time measurement of the current implementations on one machine, not a universal guarantee for every app. Still, they are a useful snapshot of where FobX stands today: faster in every measured benchmark group, with the largest gains in core reactivity overhead and mutation-heavy collection paths.
Headline results
- FobX was faster in all 64 of 64 benchmark groups.
- Overall geometric-mean speedup: 2.56x.
- Overall median speedup: 2.37x.
- Real-world suite geometric-mean speedup: 2.10x.
- Smallest win: 1.06x on
set-create-empty. - Largest win: 13.60x on
action-simple.
In other words: the slowest FobX win was effectively a tie, and the strongest wins were not marginal - they were order-of-magnitude improvements in some of the primitive reactivity paths.
Suite breakdown
When comparing mixed workloads, geometric mean is the most useful rollup because the benchmark set spans everything from sub-200 ns operations to hundreds of microseconds.
| Suite | What it measures | Groups | Geometric mean | Median | Range |
|---|---|---|---|---|---|
minimal_comparison.bench.ts |
Core observables, computeds, reactions, and dependency graph operations | 21 | 3.50x | 2.86x | 1.32x to 13.60x |
collections.bench.ts |
Arrays, maps, and sets across reads, writes, batching, and reactions | 26 | 2.26x | 2.11x | 1.06x to 7.19x |
realworld.bench.ts |
App-shaped workloads such as todo lists, tables, filtering, and graph updates | 17 | 2.10x | 2.04x | 1.21x to 3.96x |
The pattern is consistent across all three suites:
- Primitive reactive operations show the biggest absolute wins.
- Collection mutation paths are usually several times faster.
- Real-world scenarios still show material wins, even when the margins are more conservative than the smallest microbenchmarks.
Representative benchmarks
Average time per iteration. Lower is better.
| Benchmark | MobX avg | FobX avg | Speedup |
|---|---|---|---|
action-simple |
1.38 us | 101.7 ns | 13.60x |
reaction-create |
2.59 us | 247.5 ns | 10.47x |
rapid-box-100-writes |
5.34 us | 595.0 ns | 8.98x |
computed-chained-3-levels |
3.42 us | 474.5 ns | 7.21x |
array-pop |
3.87 us | 538.0 ns | 7.19x |
autorun-create |
1.14 us | 229.0 ns | 4.99x |
array-batch-write-100 |
49.12 us | 9.97 us | 4.93x |
action-batching-reactions |
3.02 us | 628.0 ns | 4.82x |
map-computed-aggregation |
40.37 us | 10.20 us | 3.96x |
array-reaction-filter-sort |
26.43 us | 8.40 us | 3.14x |
dep-graph-wide-1-to-50 |
70.44 us | 26.46 us | 2.66x |
multiple-reactions-10 |
15.36 us | 6.05 us | 2.54x |
data-table-50-rows |
574.98 us | 407.96 us | 1.41x |
todo-list-app |
46.73 us | 38.59 us | 1.21x |
Three things stand out here:
- FobX is not just winning on synthetic hot loops. It is also faster on the larger app-shaped workloads in the real-world suite.
- The biggest gains cluster around bookkeeping-heavy operations — creating reactions, running transactions, propagating computed updates, and mutating observable collections.
- High-frequency writes scale especially well. Writing 100 observable boxes
(
rapid-box-100-writes) costs 8.98x less per iteration with FobX, and batching 100 reaction-triggering writes (action-batching-reactions) is 4.82x cheaper. This is where reactive runtimes often regress under load.
What the numbers suggest
At a high level, this benchmark set suggests that FobX’s lower-level runtime overhead is meaningfully smaller than MobX’s in the current implementation. That shows up in three practical ways:
-
Cheaper reactive plumbing
Creating reactions, running actions, and traversing dependency graphs are all substantially faster. This matters because application-level performance is often limited by the cost of the reactive runtime itself, not just the user code inside reactions.
-
Stronger collection mutation performance
Array, map, and set operations are consistently faster, especially writes and batched updates. If your state model leans heavily on reactive collections, this is one of the clearest advantages in the current numbers.
-
Wins that survive contact with real workloads
The real-world suite is where exaggerated microbenchmark claims usually fall apart. That did not happen here. FobX still came out ahead in every one of those scenarios, with a 2.10x geometric-mean speedup across the suite.
Benchmark methodology
- Runtime:
Deno 2.2.12 (x86_64-unknown-linux-gnu) - CPU:
11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz - Source suites:
core/__tests__/bench/minimal_comparison.bench.tscore/__tests__/bench/collections.bench.tscore/__tests__/bench/realworld.bench.ts
- Data source: 4-11-2026-baseline.json
captured with
deno task bench --json - Aggregates on this page are computed from each benchmark’s average iteration
time using
mobx_avg / fobx_avg
If you are evaluating FobX for production use, the right conclusion is not “this exact multiplier will apply to my app.” The right conclusion is that the current runtime consistently beats MobX across microbenchmarks, collection operations, and more realistic reactive workloads, which is exactly the pattern you want to see before doing app-specific profiling.