mrkeyoor.com_
Wed 05 Aug 19:54 UTC
npmUtilsupdated 05 Aug 2026

ajv

Ajv is the standard JSON Schema validator for JavaScript. You give it a JSON Schema document, it compiles the schema into a plain JavaScript validation function, and that generated code makes it the fastest spec-compliant validator in the common benchmarks. It supports JSON Schema drafts 06 through 2020-12 (draft-04 via a companion package) plus JSON Type Definition, and it is the validation engine inside ESLint, webpack, Fastify, and thousands of other tools. Beyond pass/fail it can coerce types, fill in defaults, strip unknown properties, and report structured errors with schema paths.

Verdict

If the schema is JSON Schema, use Ajv; it is the fastest and most compliant option and the whole tooling ecosystem already depends on it. If you are inventing schemas fresh in a TypeScript app, a type-inferring library like zod is usually the better developer experience.

API stability4/5v8 has been current since 2021 and additions are backward-compatible, but the v6 to v8 transition was disruptive and plenty of dependents still sit on v6, so both APIs live in the wild.
Docs4/5ajv.js.org is comprehensive, with dedicated guides for strict mode, security, and standalone compilation, though the options reference is dense and error-object docs take some digging.
Maintenance3/5Effectively one primary maintainer who has said the next major depends on sponsorship; pushed May 2026 and releases still land, but issues and PRs sit around 369 and response times are slow.
Ecosystem5/5Roughly 369M weekly downloads because ESLint, webpack, and Fastify pull it in; plugins exist for formats, custom errors, i18n, and extra keywords.

Use it if

  • You validate against actual JSON Schema documents: OpenAPI request bodies, JSON config files with published schemas, or contracts shared with non-JavaScript services
  • Validation sits on a hot path (every API request) and you can compile schemas once at startup, because the compiled functions are dramatically faster than tree-walking validators
  • You need spec behaviors that hand-rolled validators skip: $ref across schemas, recursive references, unicode-correct string lengths, or the discriminator and nullable OpenAPI keywords
  • You want validation plus data massaging in one pass: coerceTypes for query strings, useDefaults for optional fields, removeAdditional for strict APIs
Skip it if

Setup reality

npm install ajv is clean, four small dependencies, no native code. The surprises come at first run: format keywords like email and date-time silently need the separate ajv-formats package or compilation throws in strict mode; strict mode itself (on by default in v8) errors on unknown keywords and suspect schema patterns that older tutorials use freely; and JSON Type Definition support lives at a different import path (ajv/dist/jtd) with a different class. TypeScript users get good types, but JSONSchemaType requires optional properties be marked nullable in ways that surprise people. CSP-restricted environments must precompile with ajv-cli.

Patterns

Compile a schema and validate datacompile-and-validate

import Ajv from "ajv";

const ajv = new Ajv();
const schema = {
  type: "object",
  properties: {
    name: { type: "string" },
    age: { type: "integer", minimum: 0 },
  },
  required: ["name"],
  additionalProperties: false,
};

const validate = ajv.compile(schema);
if (!validate(data)) console.log(validate.errors);

Compile once and reuse the function; compiling per request throws away Ajv's whole performance advantage. Errors live on validate.errors, not a return value.

Enable email, date-time, and other formatsadd-formats

import Ajv from "ajv";
import addFormats from "ajv-formats";

const ajv = new Ajv();
addFormats(ajv);

const validate = ajv.compile({ type: "string", format: "email" });

Since v8, formats are not bundled. Without ajv-formats, compiling a schema that uses format throws in strict mode rather than silently passing.

Report every error instead of the firstcollect-all-errors

import Ajv from "ajv";

const ajv = new Ajv({ allErrors: true });
const validate = ajv.compile(schema);
validate(data);
// validate.errors is now an array of every failure

The docs warn allErrors can be exploited for denial of service on untrusted input, since hostile payloads can generate huge error arrays. Use it for forms, not raw internet input.

Type the schema against a TypeScript interfacetypescript-typed-schema

import Ajv, { JSONSchemaType } from "ajv";

interface User {
  name: string;
  age?: number;
}

const schema: JSONSchemaType<User> = {
  type: "object",
  properties: {
    name: { type: "string" },
    age: { type: "integer", nullable: true },
  },
  required: ["name"],
};

const validate = new Ajv().compile(schema);
if (validate(data)) {
  // data is narrowed to User here
}

Optional properties must be declared nullable: true in the schema or JSONSchemaType rejects it. The compiled function is a type guard, which is the main payoff.

Coerce string inputs to schema typescoerce-query-params

import Ajv from "ajv";

const ajv = new Ajv({ coerceTypes: true });
const validate = ajv.compile({
  type: "object",
  properties: {
    page: { type: "integer" },
    active: { type: "boolean" },
  },
});

const q = { page: "2", active: "true" };
validate(q); // q is now { page: 2, active: true }

Coercion mutates the input object in place. Handy for query strings and env vars, surprising if you did not expect your data to change.

Fill defaults and remove unknown propertiesdefaults-and-strip-unknown

import Ajv from "ajv";

const ajv = new Ajv({ useDefaults: true, removeAdditional: true });
const validate = ajv.compile({
  type: "object",
  properties: {
    limit: { type: "integer", default: 20 },
  },
  additionalProperties: false,
});

const body = { limit: undefined, junk: 1 };
validate(body); // junk removed, limit set to 20

removeAdditional only strips where additionalProperties: false is set, and both options mutate input. Combining removeAdditional with anyOf has documented footguns.

Share schemas with $refreference-shared-schemas

import Ajv from "ajv";

const ajv = new Ajv();
ajv.addSchema({
  $id: "https://example.com/address.json",
  type: "object",
  properties: { city: { type: "string" } },
});

const validate = ajv.compile({
  type: "object",
  properties: {
    home: { $ref: "https://example.com/address.json" },
  },
});

Remote references are never fetched over the network; every referenced schema must be added with addSchema before compile, or compilation throws.

Add a custom validation keywordcustom-keyword

import Ajv from "ajv";

const ajv = new Ajv();
ajv.addKeyword({
  keyword: "evenNumber",
  type: "number",
  validate: (schemaVal, data) => !schemaVal || data % 2 === 0,
});

const validate = ajv.compile({ type: "number", evenNumber: true });

Without registering the keyword, strict mode rejects the schema outright. Code-generating keywords are faster than validate functions but far more work.

Add a custom string formatcustom-format

import Ajv from "ajv";

const ajv = new Ajv();
ajv.addFormat("hex-color", /^#[0-9a-f]{6}$/i);

const validate = ajv.compile({ type: "string", format: "hex-color" });

A regex is enough for simple cases; pass a function for logic. Beware writing formats with catastrophic backtracking if input is untrusted.

Validate with JSON Type Definition insteadjson-type-definition

import Ajv from "ajv/dist/jtd";

const ajv = new Ajv();
const schema = {
  properties: {
    name: { type: "string" },
  },
  optionalProperties: {
    age: { type: "uint32" },
  },
};

const validate = ajv.compile(schema);

JTD is a separate, simpler schema language (RFC 8927) with its own Ajv class at a different import path. Do not mix JTD and JSON Schema keywords.

Precompile validators for CSP-restricted runtimesstandalone-precompiled

npx ajv compile -s schema.json -o validate.js --strict=true

// then at runtime, no codegen needed:
// import validate from "./validate.js";
// validate(data);

This is the supported answer for environments that forbid new Function. The generated module still needs Ajv's small runtime helpers as a dependency.

Alternatives

PackageRegistryPick it when
zodnpmTypeScript-first validation where you want static types inferred from the schema instead of writing JSON Schema.
@exodus/schemasafenpmYou need JSON Schema validation without eval or new Function for strict CSP environments.
joinpmServer-side validation with a chainable builder API and rich built-in messages, no JSON Schema requirement.