Skip to content

Benchmarks

These benchmarks compare dot against commonly used JavaScript validation libraries using the same schemas, data, runners, and bundlers. They are about user outcomes, not lab purity. Concrete improvements are welcome: if you see a better way to measure something, please open an issue or pull request.

The benchmarks do not test who has the longest feature list. They test common boundary-validation work that each library supports.

Any callouts about dot’s performance or advantages are scoped to this benchmark harness and its fixtures.

Setup

Each benchmark fixture runs in a separate process to isolate V8 warmup, optimization, and deoptimization state between tests.

Toolchain

  • esbuild: 0.28.1
  • mitata: 1.0.34
  • rollup: 4.62.2

Environment

  • Node.js 26.1.0
  • TypeScript: 6.0.3
  • macOS Tahoe 25.5.1
  • 128 GB RAM
  • Clock: ~4.46 GHz
  • CPU: Apple M4 Max

Absolute timings vary by machine; relative comparisons are much more useful.

Libraries Tested

These benchmarks focus on function-style and fluent validators. Libraries such as TypeBox and ArkType, whose compiled schemas dominate cached comparisons, are excluded because they use a different validation model based on code-generation. Zod v4 uses a code-generation technique for an object fast path, but code-generation is not its primary validation model. The other validators in this test, including dot, do not leverage code-generation.

It is common knowledge that compiled C executes faster than an interpreted language. A benchmark proving this merely states the obvious. This is similar to a code-generation vs. interpreted validator.

Lines of Code (LOC) are source-code lines counted with tests, benchmarks, comments, and blank lines excluded. Commits identify the source checkout used for LOC and file counts.

NameVersionCommitFilesLOC
dot0.8.13c0c96d382,376
zod v44.4.3bbc68f998217,758
zod v33.25.76bbc68f99135,021
zod/mini4.4.3bbc68f997916,445
valibot1.4.1ff7c8d5456625,709
yup1.7.1ff31eee333,981
joi18.2.3c86ddc0319,388
superstruct2.0.2e414c8a91,194
runtypes7.0.416d83ca542,587

Reproduce

The harness is documented in detail so these results can be reproduced. If you are curious, you can have the benchmarks running in a couple of minutes.

Installation

bash
git clone git@github.com:sajajs/dot.git dot
cd dot
npm install
cd benchmarks
npm install

Run Benchmarks

The benchmarks must be executed from the $REPO_ROOT/benchmarks directory.

bash
# run performance benchmarks
npm run perf

# run performance benchmarks for selected libraries
# library name: dot, zod-v4, zod-v3, zod-mini, valibot, yup, joi, superstruct, runtypes.
npm run perf -- zod-v4 yup

# run bundle benchmarks
npm run bundle

# update Figures 2 and 3 after replacing the performance tables below
npm run sync-svg

# verify the figures without writing files
npm run check-svg

Fixture Scope

This benchmark suite is closed to new fixture categories for now. At roughly 4x dot’s source code, it is already large enough for the workloads it was designed to measure. Bug reports and corrections to existing fixtures are welcome.

Bundle Size

This benchmark compares bundled library size, not validation performance. The fixtures are the same, with minor differences due to library APIs. The boolean test bundles a single boolean schema, and the http test bundles a large HTTP request schema. Validation is called only to prevent bundlers from optimizing the schema away. For the http test, {} is passed as input so the benchmark measures the bundled library and schema code, not the size of HTTP request data.

Bundle Summary

Dot is not always the smallest bundle. Function-style validators can be smaller in highly tree-shaken cases. Dot’s distinction is that it stays in that weight class while still providing a fluent API.

Figure 1. Absolute Bundle Size

Bundle gzip size by bundler

Values are gzip sizes from the Bundle Size tables.

Detailed Bundle Results

boolean

librollup minrollup gzipesbuild minesbuild gzip
dot2.91 KB1.25 KB20.09 KB4.00 KB
zod v431.66 KB9.03 KB319.52 KB63.42 KB
zod v351.70 KB11.67 KB58.19 KB13.85 KB
zod/mini5.57 KB2.12 KB6.34 KB2.57 KB
valibot1.36 KB0.70 KB1.69 KB0.81 KB
superstruct2.54 KB1.11 KB2.64 KB1.16 KB
runtypes12.06 KB3.79 KB13.61 KB4.20 KB
joi187.89 KB58.82 KB172.53 KB54.68 KB
yup23.62 KB8.20 KB41.11 KB13.14 KB

http

librollup minrollup gzipesbuild minesbuild gzip
dot21.95 KB4.75 KB23.87 KB5.15 KB
zod v469.89 KB18.37 KB322.76 KB64.33 KB
zod v355.37 KB12.70 KB61.54 KB14.77 KB
zod/mini25.54 KB7.65 KB25.65 KB8.01 KB
valibot11.77 KB3.25 KB12.02 KB3.41 KB
superstruct7.80 KB3.06 KB7.92 KB3.12 KB
runtypes19.57 KB5.95 KB20.55 KB6.42 KB
joi190.81 KB59.76 KB175.35 KB55.74 KB
yup41.58 KB13.23 KB43.20 KB13.97 KB

Summary (relative to dot)

testlibrollup minrollup gzipesbuild minesbuild gzip
booleanzod v410.9x larger7.22x larger15.9x larger15.9x larger
booleanzod v317.8x larger9.33x larger2.90x larger3.46x larger
booleanzod/mini1.92x larger1.70x larger3.17x smaller1.55x smaller
booleanvalibot2.13x smaller1.78x smaller11.9x smaller4.95x smaller
booleansuperstruct1.14x smaller1.13x smaller7.61x smaller3.44x smaller
booleanruntypes4.15x larger3.03x larger1.48x smaller1.05x larger
booleanjoi64.7x larger47.0x larger8.59x larger13.7x larger
booleanyup8.13x larger6.56x larger2.05x larger3.29x larger
httpzod v43.18x larger3.86x larger13.5x larger12.5x larger
httpzod v32.52x larger2.67x larger2.58x larger2.87x larger
httpzod/mini1.16x larger1.61x larger1.07x larger1.56x larger
httpvalibot1.86x smaller1.46x smaller1.99x smaller1.51x smaller
httpsuperstruct2.81x smaller1.56x smaller3.02x smaller1.65x smaller
httpruntypes1.12x smaller1.25x larger1.16x smaller1.25x larger
httpjoi8.69x larger12.6x larger7.35x larger10.8x larger
httpyup1.89x larger2.78x larger1.81x larger2.71x larger

Performance

The performance benchmark is organized by schema size and mode.

All libraries are run with the same input data. These benchmarks measure successful boundary validation. Invalid-input diagnostics are a different workload.

Mitata can report misleading memory numbers, including occasional values that are not plausible. Treat memory results as informational. Use timing results for comparisons.

Schema Size

Schema size can be small, plain, medium, large, xlarge, or huge.

sizeprops validatedstep growth
small3-
plain227.33x
medium301.36x
large461.53x
xlarge1823.96x
huge7273.99x

The plain schema differs from the others. It is designed to have no constraints or mutation, so it measures floor validator overhead. Its 22 properties are simple primitive and container checks such as dot.string(), z.number(), arrays, records, and one small nested object.

The schemas are functionally equivalent across libraries, with minor differences due to API nuances.

Schema Mode

Mode can be cached or inline. In cached mode, the schema is constructed before the benchmark, so the test measures validation only. In inline mode, the schema is constructed inside the benchmark, so construction and validation are timed as a single unit.

Cached fixtures perform one validation before measurement, so the cached validation path is warmed. Inline fixtures measure schema construction and validation together without a separate warmup.

Dot provides over 20 opt-in prebuilt schemas outside core: including email, URL, and UUID. The medium, large, xlarge, and huge fixtures reconstruct these schemas rather than importing them, ensuring inline benchmarks include their construction cost. Each fixture contains a comment with more information.

Performance Summary

Inline ratios relative to dot are not linear. From small through large, many ratios narrow as schema construction is amortized by additional validation work. At xlarge and huge, many widen again as expanded workloads make validation scaling a larger part of the result.

Inline mode makes construction cost visible in the ratios. For libraries with higher construction cost, hoisting schemas can be an important optimization.

Dot has a different cost model. Schema construction is small enough that inline validation remains practical. That allows callers to organize code around meaning, not validator overhead.

Figure 2. Relative Validation Time

Performance time ratio relative to dot

Across 10 repeated runs, 95% of timings were within +/-4.61% of their 10-run mean, with a median drift of 0.96%. Like any microbenchmark, background CPU activity can affect individual measurements. Values are time ratios from the Performance Summary table.

Figure 3. Dot Inline vs. Cached Validators

Dot inline versus cached validators time

Comparisons are size for size: each point divides a validator's cached time by dot's inline time for the same schema. Values above 1x mean dot constructs and validates faster than the validator's cached schema.

Detailed Performance Results

dot

testmodeavg timeops/secavg mem
smallcached54.41 ns18,378,893144.36 B
smallinline104.37 ns9,581,6081.39 KB
plaincached1.44 μs694,235870.13 B
plaininline1.61 μs620,1581.35 KB
mediumcached1.02 μs979,946904.98 B
mediuminline1.60 μs624,86610.96 KB
largecached11.70 μs85,5045.71 KB
largeinline12.51 μs79,93821.70 KB
xlargecached30.01 μs33,3279.36 KB
xlargeinline32.86 μs30,43348.14 KB
hugecached53.89 μs18,55718.54 KB
hugeinline62.90 μs15,899132.58 KB

zod v4

testmodeavg timeops/secavg mem
smallcached124.05 ns8,061,426738.05 B
smallinline41.25 μs24,245161.59 KB
plaincached2.35 μs424,7323.14 KB
plaininline159.68 μs6,263659.95 KB
mediumcached1.68 μs595,984473.07 B
mediuminline290.06 μs3,448983.40 KB
largecached18.38 μs54,403131.83 KB
largeinline487.99 μs2,0491.73 MB
xlargecached63.66 μs15,708370.47 KB
xlargeinline1.20 ms8364.19 MB
hugecached118.12 μs8,466558.04 KB
hugeinline3.60 ms27712.24 MB

zod v4 medium-cached memory number seems implausible

zod v3

testmodeavg timeops/secavg mem
smallcached183.31 ns5,455,3571.31 KB
smallinline3.90 μs256,71219.42 KB
plaincached4.90 μs204,16239.44 KB
plaininline18.41 μs54,327103.39 KB
mediumcached2.97 μs336,9885.79 KB
mediuminline39.82 μs25,114137.44 KB
largecached30.22 μs33,095229.34 KB
largeinline87.58 μs11,418413.52 KB
xlargecached98.51 μs10,151643.93 KB
xlargeinline240.09 μs4,1651.06 MB
hugecached167.34 μs5,9761.06 MB
hugeinline575.61 μs1,7372.36 MB

zod/mini

testmodeavg timeops/secavg mem
smallcached226.39 ns4,417,2061.10 KB
smallinline12.61 μs79,31337.92 KB
plaincached3.15 μs317,3341.84 KB
plaininline56.60 μs17,669190.19 KB
mediumcached2.89 μs346,3622.52 KB
mediuminline123.70 μs8,084296.64 KB
largecached22.05 μs45,343137.75 KB
largeinline192.47 μs5,196568.59 KB
xlargecached74.70 μs13,386386.27 KB
xlargeinline521.67 μs1,9171.42 MB
hugecached154.84 μs6,458612.46 KB
hugeinline1.52 ms6573.76 MB

yup

testmodeavg timeops/secavg mem
smallcached1.78 μs560,7551.24 KB
smallinline8.04 μs124,34551.92 KB
plaincached76.34 μs13,099565.19 KB
plaininline115.17 μs8,683733.38 KB
mediumcached19.95 μs50,134129.92 KB
mediuminline69.90 μs14,305348.02 KB
largecached561.20 μs1,7823.97 MB
largeinline659.30 μs1,5174.34 MB
xlargecached1.67 ms59910.64 MB
xlargeinline2.06 ms48611.66 MB
hugecached2.12 ms47113.26 MB
hugeinline3.12 ms32115.90 MB

joi

testmodeavg timeops/secavg mem
smallcached489.29 ns2,043,7731.91 KB
smallinline11.24 μs88,94952.81 KB
plaincached21.91 μs45,649171.27 KB
plaininline93.01 μs10,752471.38 KB
mediumcached9.11 μs109,71539.50 KB
mediuminline101.00 μs9,901395.04 KB
largecached142.12 μs7,0361.19 MB
largeinline311.09 μs3,2151.84 MB
xlargecached420.04 μs2,3813.26 MB
xlargeinline900.75 μs1,1105.04 MB
hugecached649.69 μs1,5394.21 MB
hugeinline2.29 ms4379.85 MB

superstruct

testmodeavg timeops/secavg mem
smallcached1.36 μs733,354682.22 B
smallinline5.00 μs200,1816.04 KB
plaincached48.26 μs20,720345.76 KB
plaininline64.39 μs15,530384.19 KB
mediumcached29.79 μs33,571121.10 KB
mediuminline59.42 μs16,830183.88 KB
largecached249.93 μs4,0012.33 MB
largeinline295.17 μs3,3882.43 MB
xlargecached734.73 μs1,3616.38 MB
xlargeinline873.20 μs1,1456.65 MB
hugecached1.52 ms6598.97 MB
hugeinline1.90 ms5279.69 MB

runtypes

testmodeavg timeops/secavg mem
smallcached1.38 μs722,3711.12 KB
smallinline53.48 μs18,70085.05 KB
plaincached22.79 μs43,87089.67 KB
plaininline279.60 μs3,577459.09 KB
mediumcached23.26 μs42,99456.30 KB
mediuminline501.03 μs1,996777.40 KB
largecached136.67 μs7,317576.77 KB
largeinline908.30 μs1,1011.66 MB
xlargecached528.15 μs1,8931.85 MB
xlargeinline3.17 ms3155.62 MB
hugecached1.72 ms5804.13 MB
hugeinline9.31 ms10714.52 MB

valibot

testmodeavg timeops/secavg mem
smallcached170.75 ns5,856,443344.80 B
smallinline3.26 μs307,0162.75 KB
plaincached2.93 μs341,1073.19 KB
plaininline13.18 μs75,8976.53 KB
mediumcached1.71 μs585,419648.49 B
mediuminline29.22 μs34,22755.71 KB
largecached18.97 μs52,71230.36 B
largeinline60.89 μs16,422186.84 KB
xlargecached53.48 μs18,700285.10 KB
xlargeinline158.93 μs6,292480.91 KB
hugecached111.29 μs8,985397.69 KB
hugeinline435.71 μs2,295994.23 KB

Summary (relative to dot)

libtestmodetimememory
zod v4smallcached2.28x slower5.11x more
zod v4smallinline395.2x slower116.3x more
zod v4plaincached1.63x slower3.70x more
zod v4plaininline99.0x slower487.1x more
zod v4mediumcached1.64x slower1.91x less
zod v4mediuminline181.2x slower89.7x more
zod v4largecached1.57x slower23.1x more
zod v4largeinline39.0x slower81.4x more
zod v4xlargecached2.12x slower39.6x more
zod v4xlargeinline36.4x slower89.1x more
zod v4hugecached2.19x slower30.1x more
zod v4hugeinline57.3x slower94.6x more
zod v3smallcached3.37x slower9.28x more
zod v3smallinline37.3x slower14.0x more
zod v3plaincached3.40x slower46.4x more
zod v3plaininline11.4x slower76.3x more
zod v3mediumcached2.91x slower6.55x more
zod v3mediuminline24.9x slower12.5x more
zod v3largecached2.58x slower40.2x more
zod v3largeinline7.00x slower19.1x more
zod v3xlargecached3.28x slower68.8x more
zod v3xlargeinline7.31x slower22.6x more
zod v3hugecached3.11x slower58.6x more
zod v3hugeinline9.15x slower18.2x more
zod/minismallcached4.16x slower7.78x more
zod/minismallinline120.8x slower27.3x more
zod/miniplaincached2.19x slower2.17x more
zod/miniplaininline35.1x slower140.4x more
zod/minimediumcached2.83x slower2.85x more
zod/minimediuminline77.3x slower27.1x more
zod/minilargecached1.89x slower24.1x more
zod/minilargeinline15.4x slower26.2x more
zod/minixlargecached2.49x slower41.3x more
zod/minixlargeinline15.9x slower30.3x more
zod/minihugecached2.87x slower33.0x more
zod/minihugeinline24.2x slower29.0x more
yupsmallcached32.8x slower8.80x more
yupsmallinline77.1x slower37.4x more
yupplaincached53.0x slower665.1x more
yupplaininline71.4x slower541.3x more
yupmediumcached19.5x slower147.0x more
yupmediuminline43.7x slower31.7x more
yuplargecached48.0x slower711.1x more
yuplargeinline52.7x slower205.0x more
yupxlargecached55.6x slower1163.9x more
yupxlargeinline62.6x slower248.0x more
yuphugecached39.4x slower732.2x more
yuphugeinline49.6x slower122.8x more
joismallcached8.99x slower13.6x more
joismallinline107.7x slower38.0x more
joiplaincached15.2x slower201.6x more
joiplaininline57.7x slower347.9x more
joimediumcached8.93x slower44.7x more
joimediuminline63.1x slower36.0x more
joilargecached12.2x slower212.8x more
joilargeinline24.9x slower86.8x more
joixlargecached14.0x slower357.0x more
joixlargeinline27.4x slower107.1x more
joihugecached12.1x slower232.6x more
joihugeinline36.4x slower76.0x more
superstructsmallcached25.1x slower4.73x more
superstructsmallinline47.9x slower4.35x more
superstructplaincached33.5x slower406.9x more
superstructplaininline39.9x slower283.5x more
superstructmediumcached29.2x slower137.0x more
superstructmediuminline37.1x slower16.8x more
superstructlargecached21.4x slower418.2x more
superstructlargeinline23.6x slower114.6x more
superstructxlargecached24.5x slower697.5x more
superstructxlargeinline26.6x slower141.3x more
superstructhugecached28.2x slower495.3x more
superstructhugeinline30.1x slower74.8x more
runtypessmallcached25.4x slower7.93x more
runtypessmallinline512.4x slower61.2x more
runtypesplaincached15.8x slower105.5x more
runtypesplaininline173.4x slower338.8x more
runtypesmediumcached22.8x slower63.7x more
runtypesmediuminline313.1x slower70.9x more
runtypeslargecached11.7x slower101.0x more
runtypeslargeinline72.6x slower78.6x more
runtypesxlargecached17.6x slower202.3x more
runtypesxlargeinline96.5x slower119.4x more
runtypeshugecached32.0x slower228.3x more
runtypeshugeinline148.0x slower112.1x more
valibotsmallcached3.14x slower2.39x more
valibotsmallinline31.2x slower1.98x more
valibotplaincached2.04x slower3.76x more
valibotplaininline8.17x slower4.82x more
valibotmediumcached1.67x slower1.40x less
valibotmediuminline18.3x slower5.08x more
valibotlargecached1.62x slower192.6x less
valibotlargeinline4.87x slower8.61x more
valibotxlargecached1.78x slower30.5x more
valibotxlargeinline4.84x slower9.99x more
valibothugecached2.07x slower21.4x more
valibothugeinline6.93x slower7.50x more

zod v4 medium-cached and valibot large-cached memory numbers seem implausible