Performance Optimization Guide
Recommendations
- Reuse the same schema object and let the default validator cache hit.
- Adjust caching policy via
s.config({ cache })ornew Validator({ cache }). - Avoid repeatedly constructing DSL in loops for hotspot paths.
- Reuse a long-lived
Validatorinstance in servers; creating one per request resets the validator engine and the instance cache. - If you already manage low-level validation instances yourself, consider batch paths like
SchemaUtils.validateBatch().
Current benchmark baseline
Every value in this section comes from the tracked test/benchmarks/performance-docs-snapshot.json; values from separate benchmark reports are no longer combined. Environment: Node.js v20.20.2, win32-x64, Zod 4.3.6; run start time 2026-07-13T09:55:17.579Z.
This full matrix contains 19 comparable scenarios counted in the winner summary plus one async throw-path diagnostic scenario (AV2_THROW) that is not counted. Among comparable scenarios, schema-dsl wins 14/19 and Zod wins 5/19. Near-parity scenarios can change winner between runs, so treat the matrix as a regression signal for this repository, not as a permanent public performance claim.
The matrix documents semantic differences in its JSON report. It compares the closest supported behavior rather than claiming that every pair has identical implementation semantics.
Use these numbers as a regression baseline for this project. Re-run the benchmark when Node.js, dependencies, schema complexity, or error formatting behavior changes.
Recommended practices
Request-time DSL and memory boundaries
Calling s() itself does not keep unbounded global state. The common production risk is not "every request calls s() and therefore always leaks"; the risk is creating an unlimited number of different schema structures on a hot path.
The built-in cache helps when the same schema structure is reused. It cannot make an unbounded stream of never-repeated schemas cheap: schema-dsl's managed cache is bounded, but each miss still pays conversion and validator compilation cost.
Validator lifecycle in servers
Do not create a new Validator for every normal API request:
This is not usually a long-term memory leak if the instance is not retained, but it discards the per-instance cache and forces new validator/cache objects through allocation and garbage collection. Prefer one application-level validator, or a small set of validators for distinct option profiles.
For truly one-off, high-cardinality dynamic schemas, isolate that path and keep the validator short-lived, but do not store request-created validators or schema objects in application-level collections.
When is lower-level optimization needed?
- You need to reuse the same
Validatorinstance for a long time and observe the hit rate. - You need to explicitly control cache size, TTL, or statistics switches.
- You maintain low-level validation instances and need to use
SchemaUtils.validateBatch().
Verify command
The guard runs each tracked scenario three times and uses the median. On the same Node.js version, platform, and CPU, the schema-dsl/Zod ratio must remain at least 75% of baseline. If absolute throughput falls below the threshold, it is marked CALIBRATED only when the same-run Zod workload shows the same host-load slowdown; otherwise the gate still fails. Different environments use only the same-run relative ratio. Zod is a pinned calibration workload, not a product-performance claim.
Corresponding sample file
Example entry: performance-guide.ts
Description: Shows schema and validator reuse, cache statistics, and timing metadata added by SchemaUtils.withPerformance().