Benchmarks
schiva compared with ajv and nine other JSON Schema validators: how many tests of the JSON-Schema-Test-Suite each one passes, how fast it validates the suite and realistic payloads, how fast it compiles a schema, and how fast the features beyond validating are.
Summary
schiva passes every test of the five drafts it supports. In the same mode, it validates faster than every other library in every benchmark on this page, compiles faster than every other library that compiles schemas, and is faster than ajv on every feature they share (2.5× on average).
Every chart compares libraries doing the same work: pick the mode above it. true/false only tells whether the value is valid; first error stops at the first failing check and builds its error; all errors builds every error. Longer is faster, and next to each library is how many times slower than schiva it is.
Tests passed
Tests of the JSON-Schema-Test-Suite each library gets right, draft by draft (a schema it cannot compile counts as wrong for every test of its group). Only schiva and ajv run draft-04 and draft-06 here; drafts 2019-09 and 2020-12 run with the libraries that implement them.
| draft-04 | draft-06 | draft-07 | 2019-09 | 2020-12 | |
|---|---|---|---|---|---|
| schiva | 618 / 618 | 841 / 841 | 929 / 929 | 1261 / 1261 | 1301 / 1301 |
| ajv | 610 / 618 | 833 / 841 | 921 / 929 | 1233 / 1261 | 1239 / 1301 |
| @exodus/schemasafe | not run | not run | 905 / 929 | 1228 / 1261 | 1263 / 1301 |
| @cfworker/json-schema | not run | not run | 919 / 929 | 1248 / 1261 | 1249 / 1301 |
| json-schema-library | not run | not run | 907 / 929 | 1260 / 1261 | 1291 / 1301 |
| is-my-json-valid | not run | not run | 801 / 929 | not run | not run |
| jsen | not run | not run | 762 / 929 | not run | not run |
| djv | not run | not run | 791 / 929 | not run | not run |
| jsonschema | not run | not run | 905 / 929 | not run | not run |
| tv4 | not run | not run | 805 / 929 | not run | not run |
| z-schema | not run | not run | 859 / 929 | not run | not run |
Speed on the test suite
How many times per second each library validates every test of the groups all the libraries of the draft pass, so that each one does the same work.
Draft-07
runs per second over 430 tests
Draft 2019-09
runs per second over 1178 tests
Draft 2020-12
runs per second over 1051 tests
Draft-07
runs per second over 430 tests
Draft 2019-09
runs per second over 1178 tests
Draft 2020-12
runs per second over 1051 tests
Draft-07
runs per second over 430 tests
Draft 2019-09
runs per second over 1178 tests
Draft 2020-12
runs per second over 1051 tests
ajv's speed on drafts 2019-09 and 2020-12 changes a lot from one process to the next (between about 4k and 15k runs per second in our runs).
All the numbers
| Runs per second | draft-07 | 2019-09 | 2020-12 |
|---|---|---|---|
| schiva (boolean) | 177k | 30.9k | 34.7k |
| @exodus/schemasafe (boolean) | 147k | 24.0k | 27.5k |
| schiva (first error) | 124k | 22.1k | 25.7k |
| schiva (all errors) | 101k | 17.1k | 19.4k |
| @exodus/schemasafe (first error) | 98.2k | 14.9k | 17.1k |
| @exodus/schemasafe (all errors) | 63.9k | 6.85k | 9.72k |
| ajv (first error) | 60.2k | 4.02k | 13.8k |
| ajv (all errors) | 51.5k | 3.61k | 11.7k |
| jsen | 42.6k | – | – |
| is-my-json-valid | 33.9k | – | – |
| djv | 5.54k | – | – |
| @cfworker/json-schema | 1.22k | 251 | 276 |
| json-schema-library | 1.00k | 55 | 74 |
| jsonschema | 269 | – | – |
| tv4 | 95 | – | – |
| z-schema | 51 | – | – |
Speed on payloads
Validations per second of one value, valid and invalid, by each library that compiles the schema and gives the right answer for it. The schemas are in bench/lib/cases.js.
moltar strict
The flat object of typescript-runtime-type-benchmarks, with no extra keys allowed.
moltar strict, valid
validations per second
moltar strict, invalid
validations per second
order (20 lines)
A business object with 20 order lines: pattern, enum, const, number ranges, anyOf, nullable types, uniqueItems.
order (20 lines), valid
validations per second
order (20 lines), invalid
validations per second
order 2020-12, unevaluatedProperties (20 lines)
The same order in draft 2020-12, with $ref, allOf and unevaluatedProperties.
order 2020-12, unevaluatedProperties (20 lines), valid
validations per second
order 2020-12, unevaluatedProperties (20 lines), invalid
validations per second
payment 2020-12, oneOf + unevaluatedProperties
A payment whose variant (oneOf) decides the keys it may have (unevaluatedProperties).
payment 2020-12, oneOf + unevaluatedProperties, valid
validations per second
payment 2020-12, oneOf + unevaluatedProperties, invalid
validations per second
shapes, discriminator (8 kinds)
A shape among 8, picked by an OpenAPI discriminator (ajv with its option discriminator: true).
shapes, discriminator (8 kinds), valid
validations per second
shapes, discriminator (8 kinds), invalid
validations per second
moltar strict
The flat object of typescript-runtime-type-benchmarks, with no extra keys allowed.
moltar strict, valid
validations per second
moltar strict, invalid
validations per second
order (20 lines)
A business object with 20 order lines: pattern, enum, const, number ranges, anyOf, nullable types, uniqueItems.
order (20 lines), valid
validations per second
order (20 lines), invalid
validations per second
order 2020-12, unevaluatedProperties (20 lines)
The same order in draft 2020-12, with $ref, allOf and unevaluatedProperties.
order 2020-12, unevaluatedProperties (20 lines), valid
validations per second
order 2020-12, unevaluatedProperties (20 lines), invalid
validations per second
payment 2020-12, oneOf + unevaluatedProperties
A payment whose variant (oneOf) decides the keys it may have (unevaluatedProperties).
payment 2020-12, oneOf + unevaluatedProperties, valid
validations per second
payment 2020-12, oneOf + unevaluatedProperties, invalid
validations per second
shapes, discriminator (8 kinds)
A shape among 8, picked by an OpenAPI discriminator (ajv with its option discriminator: true).
shapes, discriminator (8 kinds), valid
validations per second
shapes, discriminator (8 kinds), invalid
validations per second
moltar strict
The flat object of typescript-runtime-type-benchmarks, with no extra keys allowed.
moltar strict, valid
validations per second
moltar strict, invalid
validations per second
order (20 lines)
A business object with 20 order lines: pattern, enum, const, number ranges, anyOf, nullable types, uniqueItems.
order (20 lines), valid
validations per second
order (20 lines), invalid
validations per second
order 2020-12, unevaluatedProperties (20 lines)
The same order in draft 2020-12, with $ref, allOf and unevaluatedProperties.
order 2020-12, unevaluatedProperties (20 lines), valid
validations per second
order 2020-12, unevaluatedProperties (20 lines), invalid
validations per second
payment 2020-12, oneOf + unevaluatedProperties
A payment whose variant (oneOf) decides the keys it may have (unevaluatedProperties).
payment 2020-12, oneOf + unevaluatedProperties, valid
validations per second
payment 2020-12, oneOf + unevaluatedProperties, invalid
validations per second
shapes, discriminator (8 kinds)
A shape among 8, picked by an OpenAPI discriminator (ajv with its option discriminator: true).
shapes, discriminator (8 kinds), valid
validations per second
shapes, discriminator (8 kinds), invalid
validations per second
All the numbers
moltar strict
The flat object of typescript-runtime-type-benchmarks, with no extra keys allowed.
| Validations per second | valid | invalid |
|---|---|---|
| schiva (boolean) | 38.5M | 110M |
| schiva (first error) | 33.1M | 78.9M |
| schiva (all errors) | 30.6M | 20.8M |
| ajv (first error) | 29.1M | 36.0M |
| ajv (all errors) | 27.9M | 17.5M |
| is-my-json-valid | 23.4M | 16.2M |
| @exodus/schemasafe (boolean) | 9.18M | 13.1M |
| @exodus/schemasafe (first error) | 9.06M | 11.7M |
| jsen | 6.70M | 7.95M |
| @exodus/schemasafe (all errors) | 5.65M | 4.49M |
| tv4 | 333k | 15.8k |
| json-schema-library | 250k | 135k |
| @cfworker/json-schema | 187k | 164k |
| jsonschema | 24.3k | 23.3k |
| z-schema | 5.84k | 5.50k |
| djv | – | 89.3k |
Left out: djv: wrong result (false).
order (20 lines)
A business object with 20 order lines: pattern, enum, const, number ranges, anyOf, nullable types, uniqueItems.
| Validations per second | valid | invalid |
|---|---|---|
| schiva (boolean) | 2.37M | 17.0M |
| schiva (all errors) | 2.23M | 1.86M |
| schiva (first error) | 2.16M | 17.1M |
| is-my-json-valid | 1.69M | 1.51M |
| ajv (first error) | 737k | 12.2M |
| ajv (all errors) | 712k | 439k |
| @exodus/schemasafe (first error) | 546k | 7.20M |
| @exodus/schemasafe (boolean) | 504k | 7.49M |
| @exodus/schemasafe (all errors) | 361k | 323k |
| jsen | 161k | 4.89M |
| json-schema-library | 14.0k | 12.8k |
| @cfworker/json-schema | 8.58k | 8.50k |
| jsonschema | 3.00k | 2.97k |
| z-schema | 2.04k | 1.94k |
| tv4 | 1.36k | 16.7k |
| djv | – | 99.6k |
Left out: djv: wrong result (false).
order 2020-12, unevaluatedProperties (20 lines)
The same order in draft 2020-12, with $ref, allOf and unevaluatedProperties.
| Validations per second | valid | invalid |
|---|---|---|
| schiva (boolean) | 2.46M | 36.7M |
| schiva (first error) | 2.32M | 31.7M |
| schiva (all errors) | 2.29M | 1.53M |
| ajv (first error) | 657k | 15.0M |
| ajv (all errors) | 655k | 381k |
| @exodus/schemasafe (boolean) | 572k | 10.9M |
| @exodus/schemasafe (first error) | 549k | 10.1M |
| @exodus/schemasafe (all errors) | 320k | 281k |
| @cfworker/json-schema | 7.97k | 7.84k |
| json-schema-library | 730 | 464 |
payment 2020-12, oneOf + unevaluatedProperties
A payment whose variant (oneOf) decides the keys it may have (unevaluatedProperties).
| Validations per second | valid | invalid |
|---|---|---|
| schiva (boolean) | 16.2M | 15.5M |
| schiva (all errors) | 15.3M | 13.8M |
| schiva (first error) | 15.2M | 14.5M |
| ajv (first error) | 8.81M | 7.54M |
| ajv (all errors) | 8.00M | 6.21M |
| @exodus/schemasafe (first error) | 7.21M | 4.89M |
| @exodus/schemasafe (boolean) | 7.12M | 6.01M |
| @exodus/schemasafe (all errors) | 4.23M | 2.99M |
| json-schema-library | 140k | 8.42k |
| @cfworker/json-schema | 103k | 90.9k |
shapes, discriminator (8 kinds)
A shape among 8, picked by an OpenAPI discriminator (ajv with its option discriminator: true).
| Validations per second | valid | invalid |
|---|---|---|
| schiva (boolean) | 121M | 162M |
| schiva (first error) | 117M | 122M |
| schiva (all errors) | 105M | 44.3M |
| is-my-json-valid | 85.1M | 38.7M |
| ajv (first error) | 44.8M | 37.1M |
| ajv (all errors) | 44.7M | 19.7M |
| @exodus/schemasafe (boolean) | 30.9M | 41.3M |
| @exodus/schemasafe (first error) | 29.8M | 32.7M |
| @exodus/schemasafe (all errors) | 16.8M | 13.3M |
| jsen | 1.68M | 1.76M |
| djv | 85.5k | 109k |
| json-schema-library | 37.9k | 26.0k |
| @cfworker/json-schema | 34.2k | 35.8k |
| jsonschema | 6.47k | 6.25k |
| tv4 | 2.98k | 2.47k |
| z-schema | 1.67k | 1.64k |
Compiling
Schemas per second, from the order schema to a function that validates it. jsonschema, tv4 and @cfworker/json-schema interpret the schema instead of compiling it: their "compiling" only builds an object, and they pay for it at every validation, which is why they are the slowest on the payloads above.
Compiling the order schema
schemas per second, first error
All the numbers
| Schemas per second | order schema |
|---|---|
| jsonschema | 80.4k |
| tv4 | 79.6k |
| @cfworker/json-schema | 31.6k |
| schiva (boolean) | 10.6k |
| schiva (first error) | 8.41k |
| schiva (all errors) | 8.29k |
| json-schema-library | 8.02k |
| jsen | 5.37k |
| is-my-json-valid | 3.53k |
| djv | 3.47k |
| z-schema | 1.20k |
| @exodus/schemasafe (boolean) | 1.04k |
| @exodus/schemasafe (first error) | 814 |
| @exodus/schemasafe (all errors) | 703 |
| ajv (all errors) | 228 |
| ajv (first error) | 191 |
Speed of the features
schiva and ajv on the features beyond validating JSON Schema, each with the same options and plugins (ajv-keywords, ajv-formats, ajv-draft-04, ajv's standalone code), with schiva's speed in times ajv's. With the options that change the data, each call validates a new object, made the same way for both. The cases are in bench/features.js.
All the numbers
| Validations per second | schiva, all errors | ajv, all errors | schiva, first error | ajv, first error | schiva / ajv |
|---|---|---|---|---|---|
| custom keyword (validate) | 879M | 114M | 899M | 118M | 7.7× |
| ajv-keywords (range, regexp, prohibited, uniqueItemProperties) | 28.5M | 22.2M | 28.3M | 22.1M | 1.3× |
| useDefaults and removeAdditional (defaults filled, 2 keys removed) | 2.64M | 2.38M | 2.62M | 2.41M | 1.1× |
| coerceTypes (query string values) | 19.2M | 14.1M | 19.4M | 14.4M | 1.4× |
| formats with formatMinimum and formatMaximum | 876k | 759k | 869k | 769k | 1.2× |
| tagged oneOf without discriminator (8 kinds) | 103M | 3.93M | 115M | 5.72M | 26.2× |
| draft-04 (boolean exclusiveMaximum, id) | 184M | 82.5M | 185M | 83.3M | 2.2× |
| error objects (order with 20 lines, invalid) | 722k | 418k | 16.9M | 12.2M | 1.7× |
| standalone code (order with 20 lines, valid) | 2.37M | 683k | 2.33M | 696k | 3.5× |
| unevaluatedProperties (payment 2020-12) | 14.2M | 7.85M | 14.9M | 8.76M | 1.8× |
schiva and ajv, feature by feature
| schiva 0.6.0 | ajv 8.20.0 | |
|---|---|---|
| JSON Schema drafts | draft-04, draft-06, draft-07, 2019-09, 2020-12 | draft-06 to 2020-12; draft-04 with ajv-draft-04 |
| JSON-Schema-Test-Suite, all five drafts | 4950 tests passed, all of them | 4836 tests passed |
| JSON Type Definition (JTD) | – | ✓ |
| Schema DSL for JavaScript | ✓ (String(), Integer()...), with inferred TypeScript types | – |
| Messages with the path of the field | ✓ (lines[3].price must be at least 0) | messages without the path; instancePath apart |
| Error objects | ✓ | ✓ |
| Every error, first error, or true/false | ✓ | ✓ |
| Standalone code | ✓ (no dependency at all) | ✓ (requires parts of ajv for some keywords) |
| Formats | ✓ built in, idn-hostname and idn-email included | with ajv-formats |
| Optional format tests passed (2020-12) | 874 / 874 | 733 / 874 (with ajv-formats) |
| formatMinimum, formatMaximum | ✓ | with ajv-formats |
| Keywords of your own: validate, compile, macro | ✓ | ✓ |
| Keywords of your own that write generated code | – | ✓ |
| ajv-keywords | ✓ built in (13 of them) | with ajv-keywords |
| useDefaults, removeAdditional, coerceTypes | ✓ | ✓ |
| $data references | – | ✓ |
| Asynchronous validation ($async) | – | ✓ |
| Loading referenced documents (compileAsync) | ✓ compileJsonSchemaAsync | ✓ |
| OpenAPI discriminator | ✓ with mapping and implicit names | const and enum only |
| Tagged oneOf detected without discriminator | ✓ | – |
| strict mode | ✓ | ✓ |
| Translated messages, errorMessage | – | with ajv-i18n, ajv-errors |
| Dependencies | 0 | 4 |
See Migrating from ajv for the options, errors and APIs of each one.
Libraries
Every library of json-schema-benchmark that runs on current Node.js, with the drafts and modes each one is benchmarked in. (ajv always returns true or false, and builds the first error, or all of them, on the way.)
| Library | Version | Drafts benchmarked | Modes benchmarked |
|---|---|---|---|
| schiva | 0.6.0 | draft-07, 2019-09, 2020-12 | all errors, first error, true/false |
| ajv | 8.20.0 | draft-07, 2019-09, 2020-12 | first error, all errors |
| @exodus/schemasafe | 1.3.0 | draft-07, 2019-09, 2020-12 | true/false, first error, all errors |
| @cfworker/json-schema | 4.1.1 | draft-07, 2019-09, 2020-12 | true/false |
| json-schema-library | 11.6.2 | draft-07, 2019-09, 2020-12 | true/false |
| is-my-json-valid | 2.20.6 | draft-07 | true/false |
| jsen | 0.6.6 | draft-07 | true/false |
| djv | 2.1.4 | draft-07 | true/false |
| jsonschema | 1.5.0 | draft-07 | true/false |
| tv4 | 1.3.0 | draft-07 | true/false |
| z-schema | 12.4.6 | draft-07 | true/false |
Method
- Every measurement runs in a new Node.js process with a single library, as a service uses it, so libraries cannot slow each other down through the state of the JIT they would share. Each one is timed for 1 second after a warm-up, in 3 processes, and the median is kept.
- Measured on 13th Gen Intel(R) Core(TM) i7-13700H, 20 cores, Windows_NT, Node.js v22.21.1, on 2026-09-30. Benchmarks depend on the machine and on what else runs on it: compare the libraries with each other, not these numbers with another machine's.
cd bench
pnpm install
pnpm start # test suite and payloads, isolated (about 30 minutes)
pnpm run features # the features of schiva and ajv
pnpm run conformance draft2020-12 # tests passed by schiva and ajv, file by file
pnpm run report # writes this page