# fast-json-stringify: schema-driven serialization for Fastify-shaped payloads

> fast-json-stringify compiles a JSON Schema Draft 7 definition into a stringify function that skips the generic traversal JSON.stringify performs. It is a good fit for small, uniform response objects in a Node.js service and a poor fit for large arrays or long strings.

**fastify/fast-json-stringify** — 2x faster than JSON.stringify()

- Repository: https://github.com/fastify/fast-json-stringify
- Website: https://npmjs.com/package/fast-json-stringify
- Stars: 3,706 · Forks: 227
- Language: JavaScript
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/fastify-fast-json-stringify

## The problem fast-json-stringify solves in a Node.js response path

JSON.stringify is generic. It walks whatever object you hand it, inspects each value at runtime, and decides how to write it. That flexibility costs time, and in a web service the same shape of object is serialized millions of times with the same set of keys in the same order. fast-json-stringify removes the runtime inspection by asking you for a JSON Schema Draft 7 definition up front and generating a function that already knows the shape. The README states that it is "significantly faster than JSON.stringify() for small payloads" and that the advantage "shrinks as your payload grows". That second clause matters as much as the first. The target user is someone running a Node.js API where the response shape is fixed and already described by a schema, which is the normal situation inside Fastify, where the framework hands the serializer a schema it already has. If you are writing a script that stringifies a config object once, this library adds a compilation step for no gain.

## How schema compilation produces a specialized stringify function

The API is a factory. You call fastJson with a schema and get back a stringify function. The README's example builds one from an object schema with firstName, lastName, age and reg properties and then calls the result on a plain object. Supported types are string, integer, number, array, object, boolean and null, plus nested combinations. A small table of special cases is worth noting because it is where hand-written serializers usually get things wrong: a Date instance is serialized as a string via toISOString(), a RegExp as a string, and a BigInt as an integer via toString. The compilation model has a cost the README quantifies. In its benchmark table, on a 4Ghz Intel Core i7 with Node.js v22.14.0, "FJS creation" runs at 9,696 ops/sec while "CJS creation" runs at 197,267 ops/sec. Building the serializer is roughly an order of magnitude slower than building a plain cached one, so the payback comes from repeated calls, not from a single one. The second argument is an options object. The keys documented in the README are schema for external $ref targets, ajv for the Ajv v8 instance settings used by anyOf, oneOf and if/then/else, rounding for how integer types are rounded when the value is not an integer, maxDepth, inlineValidators, largeArrayMechanism and compileValidators. Two of those change the cost profile rather than the output. compileValidators defaults to false, which means the Ajv validators behind anyOf, oneOf and if/then/else are compiled lazily on the first serialization that reaches them; setting it to true moves that work into build() and removes a one-off cost from the first stringify() call. maxDepth defaults to 100 and accepts values from 0 to 100, and schemas that exceed it are rejected before compilation rather than at runtime.

## Installing fast-json-stringify from npm and serializing a first object

The package is published on npm as fast-json-stringify and the repository's package.json declares version 7.0.1 with main pointing at index.js and types at types/index.d.ts, so TypeScript users get declarations without a separate package. Install it with npm.

```bash
npm install fast-json-stringify
```

The README's example is the shortest path to a working serializer. Save it as a file and run it with node. It requires the module, passes a Draft 7 object schema to the factory, and logs the result of calling the returned function.

```js
const fastJson = require('fast-json-stringify')
const stringify = fastJson({
  title: 'Example Schema',
  type: 'object',
  properties: {
    firstName: { type: 'string' },
    lastName: { type: 'string' },
    age: { description: 'Age in years', type: 'integer' },
    reg: { type: 'string' }
  }
})

console.log(stringify({
  firstName: 'Matteo',
  lastName: 'Collina',
  age: 32,
  reg: /"([^"]|\\")*" /
}))
```

You should see a JSON object printed with the four fields. The RegExp value comes out as a string, which is the documented behavior for RegExp instances. When you need to change the rounding of non-integer values passed to an integer field, or to pre-compile the Ajv validators used by union schemas, pass the options object as a second argument.

```js
const stringify = fastJson(mySchema, {
  rounding: 'ceil',
  maxDepth: 100,
  compileValidators: true
})
```

That call is documented in the README's options section. The examples directory in the repository contains example.js and server.js if you want a runnable starting point closer to a service.

## Where the speed claim stops holding: large arrays and long strings

The README's own benchmark table is the most honest part of the project's documentation, because it shows the cases where the library loses. For short strings, fast-json-stringify reaches 29,408,175 ops/sec against JSON.stringify at 12,114,052, a clear win. For plain objects it is 7,291,157 against 4,577,494. But look at large arrays: JSON.stringify runs at 331 ops/sec while "fast-json-stringify large array default" runs at 208. The default large-array mechanism is slower than the built-in. The README notes that largeArrayMechanism handles arrays of 20,000 items or more by default, and the table shows a second mode, "fast-json-stringify large array json-stringify", at 330 ops/sec, which is roughly parity rather than an advantage. Long strings are flat: JSON.stringify at 13,452 ops/sec against fast-json-stringify at 13,454. If your endpoint returns a big array of records or a long text field, the schema compilation buys you nothing and can cost you throughput. There is a second failure mode that is not about speed. The generated function follows the schema, not the object. The README devotes separate sections to Required, Missing fields, Pattern Properties, Additional Properties, AnyOf and OneOf precisely because those cases have rules you have to read. If your runtime objects drift from the schema, the output is determined by the schema rules for missing and additional fields, not by whatever keys happen to be present. That is a correctness question, not a performance one, and it is the reason to treat the schema as the contract rather than as an optional hint.

## fast-json-stringify compared with Ajv serialization and handwritten serializers

The closest alternative in the same benchmark table is AJV Serialize, which also compiles from a schema. The two differ in where the compilation cost lands. "AJV Serialize creation" is listed at 48,302,927 ops/sec, far faster to build than fast-json-stringify's 9,696 ops/sec, so if you build serializers frequently, for example one per request from a dynamic schema, Ajv is the better shape. On the serialization side the table shows fast-json-stringify obj at 7,291,157 ops/sec against AJV Serialize obj at 8,782,944, so Ajv is ahead on that payload, while on short strings fast-json-stringify is ahead at 29,408,175 against 17,841,869. The other entries in the table, json-accelerator and compile-json-stringify, sit between the two on most rows. The practical difference is not a single winner but which cost you pay once and which you pay per call. A handwritten serializer is the third option and the fastest one in principle, but it has no schema, no validation of the shape, and no documentation of what happens to a Date or a BigInt. The README's table of special cases is the part you would have to reproduce by hand and keep correct.

## Maintenance, release cadence and the MIT licence

The repository is not archived, and the last push was on 2026-09-22. Recent releases are v6.4.0 on 2026-05-05, v7.0.0 on 2026-06-09 and v7.0.1 on 2026-07-09, which means the major version moved twice in the months before the last push. The package.json version is 7.0.1, matching the latest release. The jump from 6.x to 7.x is the kind of change that can carry breaking behavior, and the README does not document a migration path from v6 to v7, so a project pinned to 6.4.0 should read the release notes rather than assume the upgrade is mechanical. The licence is MIT, declared in package.json and present as a LICENSE file at the repository root. MIT is permissive: it allows use in closed-source products provided the copyright notice and permission notice are retained. That is a description of the licence text, not legal advice, and anyone embedding the package in a distributed product should have their own counsel read the file. The repository lists funding through GitHub Sponsors and Open Collective, which is worth knowing if your organisation depends on the package. The test setup is visible in package.json: c8 with --100 --all over index.js and lib/**/*.js, run through node --test, plus a separate tstyche run for TypeScript types. A 100 percent coverage gate is a meaningful constraint on contributions, and it is also a signal that the maintainers expect changes to arrive with tests.

## What to check before replacing JSON.stringify in a service

Start by measuring the payloads you actually send. The README's numbers are for short strings, objects, dates, large arrays and long strings, and the crossover is visible in that table: short strings and small objects win, large arrays lose against the default mechanism, and long strings are a tie. If your responses are mostly large arrays, the library is the wrong tool and the schema work is wasted. Second, confirm the schema is accurate. Missing fields, additional properties, pattern properties and the anyOf and oneOf paths all have documented rules, and the generated function applies them whether or not they match your intent. Third, decide on compileValidators. Leaving it at the default false means the first request that hits a union schema pays the Ajv compilation cost; setting it to true moves that into build(), which is the right choice for a server that should not have a slow first request. Fourth, check the depth of your schema against maxDepth, which defaults to 100 and rejects deeper schemas before compilation rather than at runtime. If you already run Fastify, the framework supplies the schema and the integration is the path of least resistance. If you are not on Fastify and your payloads are large or irregular, the honest answer is that JSON.stringify is fine.

## Conclusion

Adopt fast-json-stringify when your responses are small objects with a stable shape and the schema already exists, which is the normal case inside Fastify. Do not adopt it for large arrays, long strings, or one-off serialization where the schema would have to be written from scratch, because the README's own benchmark table shows the advantage shrinking or reversing there. Before you switch, verify that your schema matches the payloads you actually emit, since the generated function follows the schema rather than the object, and check the maxDepth limit of 100 against how deeply your schema nests.

## FAQ

### What is the fastest JSON parser?

This project is a serializer, not a parser, so it does not answer that question. The README only compares stringify implementations: fast-json-stringify, JSON.stringify, AJV Serialize, json-accelerator and compile-json-stringify.

### Is JSON stringify safe?

The README includes a Security Notice section, and the library compiles a function from a JSON Schema you supply rather than from user input, so the schema is the trust boundary. The README does not document a rollback path, so a version change should be treated as a code change and tested.

### What does JSON stringify do?

In this project, fast-json-stringify takes a JSON Schema Draft 7 definition and returns a stringify function that writes values according to that schema. The README states it is significantly faster than JSON.stringify() for small payloads, with the advantage shrinking as the payload grows.

### How to make JSON stringify pretty?

The README does not document an indentation or pretty-print option for fast-json-stringify. Its options are schema, ajv, rounding, maxDepth, inlineValidators, largeArrayMechanism and compileValidators, none of which control whitespace.

## Sources

- [fastify/fast-json-stringify on GitHub](https://github.com/fastify/fast-json-stringify)
- [License: MIT](https://github.com/fastify/fast-json-stringify/blob/main/LICENSE)
- [Project website](https://npmjs.com/package/fast-json-stringify)
- [README](https://github.com/fastify/fast-json-stringify/blob/main/README.md)
- [Releases](https://github.com/fastify/fast-json-stringify/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/fastify-fast-json-stringify
