Zygos Performance Benchmarks
Performance comparison between Zygos, Neverthrow (Result) and fp-ts (Option).
Data auto-generated on Jan 29, 2026.
TL;DR
Zygos wins 80% of Result benchmarks vs Neverthrow. Up to 3x faster on object creation, 2-3x faster on chained operations. Similar performance on simple operations like isOk() and unwrapOr().
Operations per second. Higher is better.
Methodology
Each benchmark:
- Creates test data matching real-world patterns (Result chains, Option transformations)
- Runs operations in a tight loop
- Measures operations per second with statistical analysis
- Reports min, max, mean, percentiles (p75, p99, p995, p999)
- Includes relative margin of error (rme) for confidence
The "fastest" label is only awarded when the winner is ≥10% faster than the runner-up. Otherwise, it's considered a statistical tie.
Libraries Tested
| Library | Version | Description |
|---|---|---|
| zygos | 1.1.0 | Pithos Result/Option module (lightweight, tree-shakable) |
| neverthrow | 8.2.0 | Popular Result library for TypeScript |
Result Pattern (Zygos vs Neverthrow)
The Result pattern is the core of error handling in both libraries. Here's how they compare:
| Test | zygos | neverthrow |
|---|---|---|
andThen-chain | 15.63M ops/s fastest | 4.37M ops/s (3.57x) |
andThen-err | 25.10M ops/s (1x) | 25.13M ops/s fastest |
andThen-ok | 22.39M ops/s fastest | 9.93M ops/s (2.26x) |
combine-all-ok | 17.09M ops/s fastest | 6.61M ops/s (2.59x) |
combine-large | 3.58M ops/s fastest | 2.49M ops/s (1.44x) |
combine-with-err | 17.58M ops/s fastest | 6.69M ops/s (2.63x) |
err-creation | 21.04M ops/s fastest | 7.17M ops/s (2.93x) |
fromThrowable-error | 233.68K ops/s (1.01x) | 235.96K ops/s fastest |
fromThrowable-success | 4.90M ops/s fastest | 4.89M ops/s (1x) |
isErr | 25.30M ops/s fastest | 25.27M ops/s (1x) |
isOk | 25.36M ops/s fastest | 25.20M ops/s (1.01x) |
map-err | 28.47M ops/s fastest | 28.44M ops/s (1x) |
map-ok | 28.38M ops/s fastest | 28.32M ops/s (1x) |
mapErr | 28.44M ops/s fastest | 28.41M ops/s (1x) |
match-err | 28.31M ops/s (1x) | 28.32M ops/s fastest |
match-ok | 28.23M ops/s fastest | 27.99M ops/s (1.01x) |
ok-complex | 21.37M ops/s fastest | 7.13M ops/s (3x) |
ok-creation | 21.00M ops/s fastest | 9.98M ops/s (2.1x) |
unwrapOr-err | 25.17M ops/s (1x) | 25.29M ops/s fastest |
unwrapOr-ok | 25.33M ops/s fastest | 25.32M ops/s (1x) |
Key Findings
Object creation is 2-3x faster. Zygos uses simple object literals while Neverthrow uses class instantiation with more overhead.
Chained operations (andThen) are 2-4x faster. Zygos's simpler implementation pays off when chaining multiple operations.
Simple operations are equivalent. isOk(), isErr(), unwrapOr() perform identically: both are just property checks.
Option Pattern (Zygos vs fp-ts)
Zygos provides a lightweight Option implementation compared to fp-ts's more comprehensive (but heavier) approach:
| Test | Zygos | fp-ts |
|---|---|---|
| flatMap | 17.07M ops/s fastest | 2.16M ops/s (7.9x) |
| fromNullable | 21.18M ops/s fastest | 12.53M ops/s (1.69x) |
| fromNullable-null | 21.42M ops/s fastest | 12.74M ops/s (1.68x) |
| getOrElse | 20.48M ops/s fastest | 10.37M ops/s (1.98x) |
| isSome | 20.54M ops/s fastest | 12.33M ops/s (1.67x) |
| map | 20.27M ops/s fastest | 10.06M ops/s (2.01x) |
| match | 20.35M ops/s fastest | 10.00M ops/s (2.04x) |
| some-creation | 21.11M ops/s fastest | 13.70M ops/s (1.54x) |
Key Findings
Zygos is 1.5-8x faster across all Option operations. The biggest wins are on flatMap (8x) and getOrElse (2x).
fp-ts's pipe adds overhead. While elegant, the functional composition style has a runtime cost.
Zygos uses direct function calls. No intermediate abstractions, just simple conditionals.
📊 Performance Summary
Why Zygos is Fast
- Simple object literals:
{ _tag: "Ok", value }instead of class instances - No intermediate abstractions: Direct property access, no method chains
- Modern JavaScript: ES2020+ target, no transpilation overhead
- Minimal code: Less code = less to execute
When Performance Doesn't Matter
For most applications, both Zygos and Neverthrow are "fast enough". The real differentiator is:
- Bundle size: Zygos is 2.6x smaller than Neverthrow
- API ergonomics: Choose what feels right for your team
- Ecosystem: Zygos integrates with other Pithos modules
Detailed Statistics
For the skeptics who want to see the raw numbers:
Result20
andThen-chain
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 15.63M | 0.0000 | 0.0394 | 0.0001 | 0.0001 | 0.0001 | ±0.12% | 7,812,553 |
| neverthrow | 4.37M | 0.0001 | 0.0668 | 0.0002 | 0.0002 | 0.0003 | ±0.13% | 2,186,487 |
andThen-err
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| neverthrow 🏆 | 25.13M | 0.0000 | 0.0378 | 0.0000 | 0.0000 | 0.0001 | ±0.13% | 12,564,743 |
| zygos | 25.10M | 0.0000 | 0.1050 | 0.0000 | 0.0000 | 0.0001 | ±0.13% | 12,548,149 |
andThen-ok
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 22.39M | 0.0000 | 0.2858 | 0.0000 | 0.0000 | 0.0001 | ±0.20% | 11,196,072 |
| neverthrow | 9.93M | 0.0000 | 0.1548 | 0.0001 | 0.0001 | 0.0001 | ±0.17% | 4,962,641 |
combine-all-ok
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 17.09M | 0.0000 | 2.6903 | 0.0001 | 0.0001 | 0.0001 | ±1.09% | 8,546,422 |
| neverthrow | 6.61M | 0.0000 | 0.2838 | 0.0002 | 0.0002 | 0.0002 | ±0.27% | 3,303,774 |
combine-large
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 3.58M | 0.0002 | 0.2067 | 0.0003 | 0.0003 | 0.0006 | ±0.42% | 1,789,730 |
| neverthrow | 2.49M | 0.0002 | 0.2685 | 0.0004 | 0.0004 | 0.0007 | ±0.39% | 1,245,772 |
combine-with-err
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 17.58M | 0.0000 | 0.2636 | 0.0001 | 0.0001 | 0.0001 | ±0.44% | 8,789,518 |
| neverthrow | 6.69M | 0.0000 | 0.4447 | 0.0001 | 0.0002 | 0.0002 | ±0.37% | 3,346,903 |
err-creation
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 21.04M | 0.0000 | 0.1367 | 0.0000 | 0.0000 | 0.0001 | ±0.20% | 10,518,494 |
| neverthrow | 7.17M | 0.0000 | 0.1430 | 0.0001 | 0.0001 | 0.0002 | ±0.23% | 3,586,381 |
fromThrowable-error
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| neverthrow 🏆 | 235.96K | 0.0038 | 1.6269 | 0.0042 | 0.0040 | 0.0086 | ±0.79% | 117,980 |
| zygos | 233.68K | 0.0038 | 0.5621 | 0.0043 | 0.0041 | 0.0097 | ±0.50% | 116,839 |
fromThrowable-success
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 4.90M | 0.0001 | 0.0430 | 0.0002 | 0.0002 | 0.0003 | ±0.12% | 2,447,979 |
| neverthrow | 4.89M | 0.0001 | 0.1341 | 0.0002 | 0.0002 | 0.0003 | ±0.16% | 2,446,526 |
isErr
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 25.30M | 0.0000 | 0.0526 | 0.0000 | 0.0000 | 0.0001 | ±0.12% | 12,652,338 |
| neverthrow | 25.27M | 0.0000 | 0.0633 | 0.0000 | 0.0000 | 0.0001 | ±0.15% | 12,636,894 |
isOk
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 25.36M | 0.0000 | 0.0754 | 0.0000 | 0.0000 | 0.0001 | ±0.13% | 12,682,172 |
| neverthrow | 25.20M | 0.0000 | 0.0903 | 0.0000 | 0.0000 | 0.0001 | ±0.13% | 12,600,520 |
map-err
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 28.47M | 0.0000 | 0.2628 | 0.0000 | 0.0000 | 0.0000 | ±0.16% | 14,236,276 |
| neverthrow | 28.44M | 0.0000 | 0.0571 | 0.0000 | 0.0000 | 0.0000 | ±0.12% | 14,219,506 |
map-ok
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 28.38M | 0.0000 | 0.0707 | 0.0000 | 0.0000 | 0.0000 | ±0.13% | 14,187,567 |
| neverthrow | 28.32M | 0.0000 | 0.1597 | 0.0000 | 0.0000 | 0.0000 | ±0.15% | 14,159,415 |
mapErr
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 28.44M | 0.0000 | 0.0390 | 0.0000 | 0.0000 | 0.0000 | ±0.13% | 14,218,338 |
| neverthrow | 28.41M | 0.0000 | 0.0673 | 0.0000 | 0.0000 | 0.0000 | ±0.13% | 14,203,990 |
match-err
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| neverthrow 🏆 | 28.32M | 0.0000 | 0.0956 | 0.0000 | 0.0000 | 0.0000 | ±0.19% | 14,160,960 |
| zygos | 28.31M | 0.0000 | 0.1078 | 0.0000 | 0.0000 | 0.0000 | ±0.21% | 14,152,591 |
match-ok
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 28.23M | 0.0000 | 0.0685 | 0.0000 | 0.0000 | 0.0000 | ±0.13% | 14,115,862 |
| neverthrow | 27.99M | 0.0000 | 0.1938 | 0.0000 | 0.0000 | 0.0000 | ±0.23% | 13,995,988 |
ok-complex
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 21.37M | 0.0000 | 0.2407 | 0.0000 | 0.0000 | 0.0001 | ±0.23% | 10,682,566 |
| neverthrow | 7.13M | 0.0000 | 0.1102 | 0.0001 | 0.0001 | 0.0002 | ±0.24% | 3,564,423 |
ok-creation
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 21.00M | 0.0000 | 0.0781 | 0.0000 | 0.0000 | 0.0001 | ±0.21% | 10,501,012 |
| neverthrow | 9.98M | 0.0000 | 0.1812 | 0.0001 | 0.0001 | 0.0001 | ±0.24% | 4,990,318 |
unwrapOr-err
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| neverthrow 🏆 | 25.29M | 0.0000 | 0.0662 | 0.0000 | 0.0000 | 0.0001 | ±0.13% | 12,647,338 |
| zygos | 25.17M | 0.0000 | 0.1113 | 0.0000 | 0.0000 | 0.0001 | ±0.14% | 12,586,019 |
unwrapOr-ok
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 25.33M | 0.0000 | 0.1078 | 0.0000 | 0.0000 | 0.0001 | ±0.12% | 12,663,841 |
| neverthrow | 25.32M | 0.0000 | 0.3640 | 0.0000 | 0.0000 | 0.0001 | ±0.19% | 12,659,480 |
Option8
flatMap
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 17.07M | 0.0000 | 0.2398 | 0.0001 | 0.0001 | 0.0001 | ±0.27% | 8,533,278 |
| fp-ts/flatMap | 2.16M | 0.0003 | 0.3111 | 0.0005 | 0.0005 | 0.0006 | ±0.34% | 1,079,701 |
fromNullable
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 21.18M | 0.0000 | 0.4290 | 0.0000 | 0.0000 | 0.0001 | ±0.30% | 10,587,618 |
| fp-ts/fromNullable | 12.53M | 0.0000 | 0.0431 | 0.0001 | 0.0001 | 0.0001 | ±0.12% | 6,265,561 |
fromNullable-null
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 21.42M | 0.0000 | 0.0794 | 0.0000 | 0.0000 | 0.0001 | ±0.12% | 10,709,367 |
| fp-ts/fromNullable | 12.74M | 0.0000 | 0.0665 | 0.0001 | 0.0001 | 0.0001 | ±0.13% | 6,369,362 |
getOrElse
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 20.48M | 0.0000 | 0.1204 | 0.0000 | 0.0000 | 0.0001 | ±0.13% | 10,241,621 |
| fp-ts/getOrElse | 10.37M | 0.0000 | 0.0699 | 0.0001 | 0.0001 | 0.0001 | ±0.13% | 5,183,817 |
isSome
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 20.54M | 0.0000 | 0.8130 | 0.0000 | 0.0000 | 0.0001 | ±0.34% | 10,269,219 |
| fp-ts/isSome | 12.33M | 0.0000 | 0.0842 | 0.0001 | 0.0001 | 0.0001 | ±0.13% | 6,163,962 |
map
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 20.27M | 0.0000 | 0.1348 | 0.0000 | 0.0000 | 0.0001 | ±0.14% | 10,132,860 |
| fp-ts/map | 10.06M | 0.0000 | 0.3281 | 0.0001 | 0.0001 | 0.0001 | ±0.18% | 5,030,723 |
match
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 20.35M | 0.0000 | 0.3162 | 0.0000 | 0.0000 | 0.0001 | ±0.19% | 10,175,539 |
| fp-ts/match | 10.00M | 0.0000 | 0.2816 | 0.0001 | 0.0001 | 0.0001 | ±0.17% | 5,000,125 |
some-creation
| Library | ops/s | min | max | mean | p75 | p99 | rme | samples |
|---|---|---|---|---|---|---|---|---|
| zygos 🏆 | 21.11M | 0.0000 | 0.0643 | 0.0000 | 0.0000 | 0.0001 | ±0.11% | 10,553,702 |
| fp-ts/some | 13.70M | 0.0000 | 0.0586 | 0.0001 | 0.0001 | 0.0001 | ±0.13% | 6,851,485 |
Reproduce These Results
Want to verify these results? See how to reproduce our data.
Related
- Zygos vs Neverthrow — Full comparison: philosophy, API, migration
- Kanon — Performance — Validation library benchmarks
- Zygos Module Guide — Full module documentation