ajv-validator/ajv
> A JSON Schema validator that compiles schemas into specialized JavaScript validation functions — the de facto validation engine underneath much of the Node.js ecosystem.
GitHub repo · Official website · License: MIT
Overview
Ajv ("Another JSON Validator") validates data against JSON Schema. Its defining design choice is code generation: rather than interpreting a schema at validation time, ajv.compile(schema) emits a purpose-built JavaScript function for that exact schema, which the V8 engine can then JIT-optimize. This is why Ajv consistently tops JSON Schema validation benchmarks1 and why it became the default validator inside tools like Fastify, ESLint's config loader, webpack schema checks, and countless API frameworks.
Ajv supports JSON Schema drafts 06, 07, 2019-09, and 2020-12, plus JSON Type Definition (RFC 8927)2. Draft-04 support requires the separate ajv-draft-04 package. The project is maintained primarily by its original author, Evgeny Poberezkin (epoberezkin), and has received a Mozilla Open Source Support (MOSS) grant3. With roughly 14.8k stars but over 100M weekly npm downloads, it is a case where GitHub stars badly understate reach — Ajv is infrastructure, pulled in transitively far more often than it is chosen directly.
The central tension: code generation is what makes Ajv fast, and also what makes it awkward in Content-Security-Policy environments (it uses Function constructor / eval semantics), risky when compiling untrusted schemas, and the source of a difficult v6→v7/v8 migration that split the ecosystem.
Getting Started
npm install ajv
import Ajv from "ajv"
const ajv = new Ajv({ allErrors: true })
const schema = {
type: "object",
properties: {
foo: { type: "integer" },
bar: { type: "string" },
},
required: ["foo"],
additionalProperties: false,
}
const validate = ajv.compile(schema) // compile ONCE, reuse the function
if (!validate({ foo: 1, bar: "abc" })) {
console.log(validate.errors)
}
Formats (date, email, uri, etc.) are not built in since v7 — install and register ajv-formats separately:
import addFormats from "ajv-formats"
addFormats(ajv)
Architecture / How It Works
compile() walks the schema tree and, for each keyword, appends JavaScript source to a code buffer using an internal CodeGen API. The result is a single function containing inlined checks (if (typeof data.foo !== "number") ...), error-collection logic, and any referenced sub-validators. That function is instantiated once and called on every payload — validation itself does no schema traversal, which is the entire performance story.
Ajv v6 built this generated code from doT.js string templates. v7 replaced that with a typed CodeGen module that produces an AST-like intermediate form before serialization — a rewrite that improved tree-shaking, TypeScript types, and the standalone-compilation path, but changed enough internals to make v6 plugins incompatible4.
Two features that flow from the code-gen model:
- Standalone validation code —
ajv.compileoutput can be serialized to a
standalone .js module (via ajv/dist/standalone) at build time, so the runtime never calls eval/Function at all. This is the sanctioned escape hatch for CSP-restricted and edge/serverless environments.
- Data mutation — because the validator is generated per-schema, Ajv can
cheaply fold in behaviors like removeAdditional, useDefaults, and coerceTypes that mutate the input during validation. Convenient, but it means validation is not always side-effect-free.
References ($ref, $recursiveRef, $dynamicRef) are resolved at compile time; remote schemas must be registered via addSchema or loaded through the async loadSchema option before/while compiling.
Production Notes
- Compile once. The most common performance bug is calling
ajv.compile() (or ajv.validate(schema, data), which compiles internally) on every request. Compilation is expensive; the compiled function is cheap. Cache compiled validators, or use addSchema + getSchema(key).
- CSP /
unsafe-eval. Default Ajv generates code with theFunction
constructor. Under a strict Content-Security-Policy (no unsafe-eval), compilation throws. Use the standalone precompilation path at build time rather than shipping schemas to the browser and compiling there.
- Strict mode is on by default (v7+). Unknown keywords, unknown formats,
ambiguous additionalProperties/required combinations, and several other patterns now throw at compile time instead of being ignored. This is the single biggest source of "it worked in v6" migration pain. strict: false restores lenient behavior but masks real schema mistakes.
- The two-major split. Ajv 6 and Ajv 8 are incompatible and frequently
coexist in the same node_modules tree because widely-used tools pinned v6 (older ESLint, webpack, and their plugins). Expect duplicate copies; a schema and plugin must be matched to the same major (e.g. ajv-formats requires v8, ajv-keywords versions are major-specific).
- Untrusted schemas are a code-execution surface. Compiling
attacker-controlled schemas means generating and running attacker-influenced code, and format regexes can enable ReDoS. Ajv has had prototype-pollution and ReDoS advisories in its history5. Validate data from untrusted sources freely; do not compile schemas from untrusted sources.
additionalProperties: falsewithallOf/$refis a footgun — it does
not "see through" combinators, so a property allowed by a referenced schema is still rejected. This is JSON Schema semantics, not an Ajv bug, but Ajv is where people hit it.
allErrors: trueis slower and a DoS vector on hostile input (it forces
full traversal instead of failing fast); keep it off in hot paths.
When to Use / When Not
Use when:
- You need standards-compliant JSON Schema validation (OpenAPI, config files,
API request/response bodies against a spec you don't own).
- Validation is hot and you can compile schemas ahead of time.
- You want interop: schemas are portable data, not code, and work across
languages and tools.
Avoid / reconsider when:
- Your "schema" is really TypeScript types —
zodortypeboxgive you types
and validation from one source without hand-writing JSON Schema.
- You run under strict CSP and cannot use the standalone build.
- You must compile schemas supplied by end users at runtime (code-gen risk).
- You only need a couple of shape checks — Ajv's compile cost and API surface
may be overkill for a trivial guard.
Alternatives
- colinhacks/zod — TypeScript-first; schema and static type are one definition. Use when your schemas live in code, not as portable JSON.
- sinclairzx81/typebox — builds JSON Schema from TS types; frequently paired with Ajv rather than replacing it. Use when you want both TS types and a real JSON Schema to hand to Ajv.
- ExodusMovement/schemasafe — security-focused JSON Schema validator with an eval-free mode. Use when compiling untrusted schemas or under strict CSP.
- cfworker/json-schema — small, no
eval, edge-runtime friendly. Use on Cloudflare Workers / CSP-locked environments where Ajv's code-gen is a problem. - hapijs/joi — object-schema validation with a fluent JS API, not JSON Schema. Use when you want ergonomic in-code validation and don't need spec portability.
History
| Version | Date | Notes |
|---|---|---|
| 4.x | 2016 | Early widely-adopted line; draft-04. |
| 6.0.0 | 2017-12 | draft-07 support; the long-lived version many tools still pin4. |
| 7.0.0 | 2020-12 | CodeGen rewrite (dropped doT templates), strict mode default, formats split into ajv-formats4. |
| 8.0.0 | 2021-03 | Added JSON Schema 2019-09 / 2020-12 and JSON Type Definition (RFC 8927)2. |
Current development targets the v8 line; the README notes further major work is planned pending sponsorship. See the GitHub releases page for the full changelog6.
References
- ^ json-schema-benchmark, comparing JSON Schema validators (Ajv reported fastest). https://github.com/ebdrup/json-schema-benchmark
- ^ JSON Type Definition, RFC 8927. https://datatracker.ietf.org/doc/rfc8927/
- ^ Ajv README — Mozilla Open Source Support (MOSS) grant acknowledgment. https://github.com/ajv-validator/ajv
- ^ Ajv release notes for v7.0.0 (CodeGen rewrite, strict mode, formats moved out). https://github.com/ajv-validator/ajv/releases/tag/v7.0.0
- ^ Ajv security policy and advisory history (report via Tidelift). https://ajv.js.org/security.html
- ^ Ajv releases. https://github.com/ajv-validator/ajv/releases
Tags
typescript, javascript, json-schema, validation, json-type-definition, code-generation, nodejs, schema-validator, openapi, data-validation