Zod's fromJSONSchema
Back to blog

Zod's fromJSONSchema

Evaluating Zod's new method for JSONSchema validation

Jan Schutte

Zod 4.3 introduced fromJSONSchema(). We were using @cfworker/json-schema in Fragno Forms to validate form submissions on the backend. Since we already use Zod for request schemas, switching to Zod for JSON Schema validation would let us consolidate dependencies.

Why not use Ajv?

Ajv is the go-to JSON Schema validator, but it uses new Function() under the hood to generate optimized validation code. Cloudflare Workers (the workerd runtime) doesn't allow dynamic code evaluation, which is a problem since this website runs on Cloudflare Workers.

@cfworker/json-schema exists specifically for this constraint. It's a pure runtime interpreter that works in restricted environments. But if you're already using Zod, having it handle JSON Schema validation means one fewer dependency.

Benchmark

I ran a quick benchmark against the JSON-Schema-Test-Suite (draft7). In serverless environments, validators don't persist across requests, so caching compiled schemas isn't practical, we need to measure combined compile + validate time.

LibraryVersionCompileValidateTotal
@cfworker/json-schema4.1.10.0003ms0.0007ms~0.001ms
zod4.3.50.011ms0.0006ms~0.012ms
ajv8.17.12.0ms0.00009ms~2.0ms
Time to compile/validate one schema, averaged over 88 schema files, 1000 iterations, Node.js runtime, AMD Ryzen 5 7640U.

Ajv is slowest overall because code generation is expensive, but once compiled validation is extremely fast. Zod is slower than @cfworker/json-schema but still fast enough for most use cases.

Dependencies

Additionally, @jsonforms/core has an Ajv dependency for frontend validation. Removing @cfworker/json-schema means many users go from three validation libraries to two. Ideally we'd use just one, but JSONForms doesn't allow swapping out its validation library.

We dropped @cfworker/json-schema from Fragno Forms. Zod was already there for validating backend route inputs, and performance is more than acceptable for this use case.