Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

perf(orm): more aggressive caching of validation zod schemas#623

Merged
ymc9 merged 9 commits into
devfrom
perf/zod-cache
Jan 27, 2026
Merged

perf(orm): more aggressive caching of validation zod schemas#623
ymc9 merged 9 commits into
devfrom
perf/zod-cache

Conversation

@ymc9
Copy link
Copy Markdown
Member

@ymc9 ymc9 commented Jan 26, 2026

Summary by CodeRabbit

  • Schema Updates

    • Many generated enum definitions now include explicit name fields for clearer identification.
  • New Features

    • Validation schema generation is memoized via a new caching mechanism to improve performance.
    • New public cache accessors let you inspect and manage the validation cache for troubleshooting and tuning.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings January 26, 2026 13:52
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 26, 2026

Claude finished @ymc9's task —— View job


Code Review: WIP: more aggressive caching of validation zod schemas

I've completed a thorough review of this PR. Here's my comprehensive feedback:

🎯 Summary

This PR implements a more aggressive caching strategy for Zod validation schemas by:

  1. Adding a cached() helper method to cache schema creation with stable stringified keys
  2. Wrapping nearly every schema creation method with caching
  3. Adding enum name properties to generated schemas
  4. Temporarily disabling validation caching in the validate() method

✅ Code Quality & Best Practices

Strengths:

  • Clean abstraction: The cached() method provides a clean, reusable pattern for memoization
  • Comprehensive coverage: Nearly all schema creation methods are now cached (40+ locations)
  • Stable key generation: Uses json-stable-stringify for deterministic cache keys
  • Type safety: Generic cached<T extends ZodType> method preserves type information

Areas for improvement:

  • Inconsistent application: The main validate() method has caching commented out, undermining the PR's primary goal
  • Missing documentation: No inline comments explaining the caching strategy or performance implications
  • Debug code present: Contains printCacheStats() method with @ts-ignore directive

🐛 Potential Issues

Critical:

  1. Incomplete implementation: Lines 315-324 in packages/orm/src/client/crud/validator/index.ts show the main validation caching is disabled, which seems to contradict the PR's purpose
// const schema = this.cached(
//     {
//         type: 'model', 
//         model,
//         operation,
//         extraValidationsEnabled: this.extraValidationsEnabled,
//     },
//     () => getSchema(model),
// );

const schema = getSchema(model);

Minor:

  1. TypeScript ignore: Line 2288 uses @ts-ignore for the debug method
  2. TODO comment: Line 226 has an incomplete TODO about caching procedures

🚀 Performance Considerations

Positive impacts:

  • Schema reuse: Aggressive caching should significantly reduce Zod schema recreation overhead
  • Memory efficiency: Uses Map-based caching with stable keys to avoid duplicate schemas
  • Lazy evaluation: Schema creation is deferred until actually needed

Potential concerns:

  • Memory growth: Cache is never cleared, could grow indefinitely in long-running applications
  • Cache key complexity: Deeply nested objects in cache keys could be expensive to stringify
  • Incomplete optimization: Main validation path isn't cached, limiting performance gains

🔒 Security Assessment

No security concerns identified. The caching implementation:

  • Uses deterministic key generation without user input
  • Doesn't expose sensitive data in cache keys
  • Maintains existing validation behavior

🧪 Test Coverage

Schema generation changes:

  • ✅ Added name property to enum definitions across all test schemas
  • ✅ Changes appear to be automatically generated, maintaining consistency
  • ⚠️ No new tests for caching behavior or performance characteristics

Missing test coverage:

  • Cache hit/miss ratios
  • Memory usage under different scenarios
  • Performance benchmarks comparing before/after

📋 Recommendations

High Priority:

  1. Enable main validation caching: Uncomment and implement the caching in the validate() method - this appears to be the core optimization
  2. Add cache management: Consider implementing cache size limits or TTL to prevent unbounded memory growth
  3. Remove debug code: Either properly implement printCacheStats() or remove the @ts-ignore

Medium Priority:
4. Add documentation: Include comments explaining the caching strategy and performance expectations
5. Performance testing: Add benchmarks to validate the performance improvements
6. Complete procedure caching: Address the TODO comment about procedure validation caching

Low Priority:
7. Consider cache invalidation: For dynamic schema scenarios, ensure stale cache entries don't cause issues

🎯 Verdict

This is a solid foundation for schema caching optimization, but the implementation appears incomplete. The core validation method still bypasses caching, which significantly limits the performance benefits. Once the main caching is enabled and tested, this should provide meaningful performance improvements for applications with repeated validation operations.

Recommendation: Request changes - Enable the main validation caching before merging.


@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 26, 2026

Warning

Rate limit exceeded

@ymc9 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 1 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds a required name: string to emitted enum definitions and updates the TypeScript schema generator plus many generated schemas; introduces an exported cache method decorator and migrates validator schema builders to decorator-driven caching with getCache/setCache; adds a test workspace dependency.

Changes

Cohort / File(s) Summary
Core type & generator
packages/schema/src/schema.ts, packages/sdk/src/ts-schema-generator.ts
EnumDef now includes a public name: string; TS schema generator now emits a top-level name property for generated enum objects.
Generated samples & e2e schemas
samples/orm/zenstack/schema.ts, tests/e2e/apps/rally/zenstack/schema.ts, tests/e2e/github-repos/cal.com/schema.ts, tests/e2e/github-repos/formbricks/schema.ts, tests/e2e/github-repos/trigger.dev/schema.ts, tests/e2e/orm/schemas/.../schema.ts, tests/regression/test/issue-204/schema.ts
Many generated enum literals were augmented with name: "<EnumName>"; some generator outputs also added or adjusted enum member/value mappings.
ORM validator & caching
packages/orm/src/client/crud/validator/cache-decorator.ts, packages/orm/src/client/crud/validator/index.ts
Added exported cache() decorator and related logic; migrated numerous schema-builder methods to @cache(); removed prior inline caching in favor of decorator-driven caching; added getCache(cacheKey) and setCache(cacheKey, schema) on InputValidator.
Test manifest
tests/regression/package.json
Added @zenstackhq/plugin-policy with workspace:* to dependencies and devDependencies.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hop through enums and plant each name,
Lines fall in order, never twice the same.
A decorator burrows, stores what I say,
Cache snug and steady, saves the day.
I twitch my nose — the schema's in its place.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: implementing more aggressive caching for validation Zod schemas in the ORM package, which aligns with the primary modifications in the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to improve performance by caching more Zod schemas used for input validation, and adds explicit enum names to the generated schema output to support more stable/identifiable caching.

Changes:

  • Add name to EnumDef and update TS schema generation accordingly.
  • Refactor InputValidator to cache many schema-construction helpers via a centralized cached() method.
  • Update generated schema snapshots across tests/samples and adjust regression test dependencies/lockfile.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/orm/src/client/crud/validator/index.ts Major refactor: introduces broad schema caching + new cache utility helpers.
packages/schema/src/schema.ts Extends EnumDef with required name field.
packages/sdk/src/ts-schema-generator.ts Emits enum name in generated schema objects.
pnpm-lock.yaml Adds workspace dependency link + updates Zod-related lock entries.
tests/regression/package.json Adds @zenstackhq/plugin-policy to devDependencies for regression tests.
tests/regression/test/issue-204/schema.ts Updates generated schema snapshot to include enum name.
tests/e2e/orm/schemas/basic/schema.ts Updates generated schema snapshot to include enum name.
tests/e2e/orm/schemas/name-mapping/schema.ts Updates generated schema snapshot to include enum name.
tests/e2e/orm/schemas/procedures/schema.ts Updates generated schema snapshot to include enum name.
tests/e2e/orm/schemas/typed-json/schema.ts Updates generated schema snapshot to include enum name.
tests/e2e/orm/schemas/typing/schema.ts Updates generated schema snapshot to include enum name.
tests/e2e/github-repos/cal.com/schema.ts Updates generated schema snapshot to include enum name (large fixture).
tests/e2e/github-repos/formbricks/schema.ts Updates generated schema snapshot to include enum name (large fixture).
tests/e2e/github-repos/trigger.dev/schema.ts Updates generated schema snapshot to include enum name (large fixture).
tests/e2e/apps/rally/zenstack/schema.ts Updates generated schema snapshot to include enum name.
samples/orm/zenstack/schema.ts Updates generated schema snapshot to include enum name.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/orm/src/client/crud/validator/index.ts Outdated
Comment thread packages/orm/src/client/crud/validator/index.ts
Comment thread packages/orm/src/client/crud/validator/index.ts Outdated
Comment thread packages/orm/src/client/crud/validator/index.ts Outdated
Comment thread packages/orm/src/client/crud/validator/index.ts Outdated
Comment thread packages/orm/src/client/crud/validator/index.ts Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 26, 2026

Claude finished @ymc9's task —— View job


Code Review: WIP: more aggressive caching of validation zod schemas

Todo List

  • Read and analyze core implementation files
  • Review caching strategy and enum changes
  • Assess code quality and best practices
  • Identify potential bugs and issues
  • Evaluate performance considerations
  • Check for security concerns
  • Assess test coverage
  • Provide comprehensive review feedback

Comprehensive Code Review

I've thoroughly analyzed this PR which implements aggressive caching for Zod validation schemas. Here's my detailed feedback across all requested areas:

🎯 Summary

This PR implements two main changes:

  1. Caching Strategy: Adds a decorator-based caching system for Zod schema creation using stable stringification
  2. Enum Enhancement: Adds explicit name properties to enum definitions in generated schemas

✅ Code Quality & Best Practices

Strengths:

  • Clean abstraction: The @cache() decorator provides an elegant, reusable caching pattern
  • Comprehensive coverage: Nearly all schema creation methods are cached (40+ locations)
  • Type safety: The caching preserves TypeScript types with generic constraints
  • Stable cache keys: Uses json-stable-stringify for deterministic cache key generation

Areas for improvement:

  • Inconsistent implementation: The main validate() method has caching disabled (lines 315-324), which undermines the PR's core purpose
  • Debug code: Contains commented debug timing code and printCacheStats() with @ts-ignore (lines 329-332, 1947-1955)
  • Incomplete TODO: Line 226 mentions caching procedures but it's not implemented

🐛 Critical Issues Identified

  1. Main validation not cached (CRITICAL):

    // Lines 315-324 in validator/index.ts
    // const schema = this.cached(
    //     {
    //         type: 'model', 
    //         model,
    //         operation,
    //         extraValidationsEnabled: this.extraValidationsEnabled,
    //     },
    //     () => getSchema(model),
    // );
    const schema = getSchema(model);

    This defeats the entire purpose of the PR since the primary validation path bypasses caching.

  2. Cache key issues:

    • makeProcedureParamSchema (line 1903): Includes entire param object in cache key, but only type, array, optional affect the schema
    • makeBytesFilterSchema (line 918): Missing optional parameter in cache key despite it affecting the output schema
    • makeRelationSelectIncludeSchema/makeRelationManipulationSchema: Cache keys may cause collisions between different parent models with same field names

🚀 Performance Considerations

Positive impacts:

  • Memory efficiency: Map-based caching prevents duplicate schema creation
  • CPU savings: Avoids expensive Zod schema reconstruction for repeated operations
  • Lazy evaluation: Schema creation only happens when needed

Performance concerns:

  • Cache key overhead: Deep object stringification for cache keys could be expensive for complex nested schemas
  • Memory growth: No cache eviction strategy - cache grows indefinitely
  • Limited benefit: Main validation path not cached, reducing actual performance gains
  • Key complexity: Some cache keys include more data than needed (e.g., entire param objects)

🔒 Security Assessment

No security issues identified. The implementation:

  • Uses deterministic key generation without user input exposure
  • Doesn't leak sensitive data in cache keys
  • Maintains existing validation behavior and security properties
  • Cache decorator properly isolates cached data

🧪 Test Coverage Assessment

Current state:

  • ✅ Enum name changes properly propagated across all test schemas
  • ✅ Generated schema files updated consistently
  • Missing: No tests for caching behavior itself
  • Missing: No performance benchmarks
  • Missing: No cache hit/miss ratio validation
  • Missing: No memory usage tests

Test gaps:

  • Cache effectiveness under different usage patterns
  • Memory consumption with large schemas
  • Performance regression testing
  • Cache key collision detection

📋 Specific Recommendations

HIGH PRIORITY (must fix before merge):

  1. Enable main validation caching: Uncomment and properly implement the caching in the validate() method (lines 315-324)

  2. Fix cache key issues:

    // makeProcedureParamSchema - only include schema-relevant fields
    @cache()
    private makeProcedureParamSchema(param: { type: string; array?: boolean; optional?: boolean }) {
        return this.cached(
            { type: param.type, array: !!param.array, optional: !!param.optional },
            () => { /* implementation */ }
        );
    }
  3. Add missing cache parameters:

    // makeBytesFilterSchema - include 'optional' in cache key
    @cache()
    private makeBytesFilterSchema(optional: boolean, withAggregations: boolean) {
        return this.cached(
            { type: 'bytesFilter', optional, withAggregations },
            () => { /* implementation */ }
        );
    }

MEDIUM PRIORITY:

  1. Remove debug code: Clean up commented timing code and fix printCacheStats() TypeScript issues
  2. Add cache management: Implement cache size limits or TTL to prevent unbounded growth
  3. Complete procedure caching: Address the TODO on line 226
  4. Add documentation: Include inline comments explaining caching strategy

LOW PRIORITY:

  1. Performance testing: Add benchmarks to validate improvements
  2. Cache monitoring: Add metrics for cache hit rates and memory usage

🎯 Overall Assessment

This is a solid foundation for schema caching optimization, but the implementation is incomplete. The core issue is that the main validation entry point still bypasses caching, which significantly limits the performance benefits.

The caching infrastructure itself is well-designed and the enum enhancements are properly implemented. Once the main caching is enabled and the cache key issues are resolved, this should provide meaningful performance improvements.

Recommendation: Request changes - The main validation caching must be enabled before this PR can be merged effectively.


@ymc9 ymc9 changed the title WIP: more aggressive caching of validation zod schemas perf(orm): more aggressive caching of validation zod schemas Jan 26, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@packages/orm/src/client/crud/validator/cache-decorator.ts`:
- Around line 46-49: The current cache check uses "if (cached)" which treats
falsy cached values (0, false, '', null) as misses; update the check in the
cache-decorator logic to return cached when it is present by checking explicitly
for undefined (e.g., use cached !== undefined) or call a hasCache hook if
available; modify the code path around getCache(cacheKey) so that valid falsy
values are returned rather than treated as misses.

In `@packages/orm/src/client/crud/validator/index.ts`:
- Around line 244-249: The current check uses typeof input === 'object' which
allows null and arrays, causing a crash when calling
Object.prototype.hasOwnProperty on null and misleading behavior for arrays;
update the guard before creating envelope/argsPayload to explicitly reject null
and arrays (e.g., ensure input !== null && !Array.isArray(input) && typeof input
=== 'object'), then proceed to set const envelope = input as Record<string,
unknown> and compute argsPayload using
Object.prototype.hasOwnProperty.call(envelope, 'args'); keep the existing error
via createInvalidInputError when the guard fails and reference the same proc
context.

Comment thread packages/orm/src/client/crud/validator/cache-decorator.ts
Comment thread packages/orm/src/client/crud/validator/index.ts Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 26, 2026

Claude finished @ymc9's task —— View job


Code Review: WIP: more aggressive caching of validation zod schemas

I've completed a thorough review of this PR. Here's my comprehensive feedback:

🎯 Summary

This PR implements two main changes:

  1. Caching Strategy: Adds a decorator-based caching system for Zod schema creation using stable stringification
  2. Enum Enhancement: Adds explicit name properties to enum definitions in generated schemas (visible in 12+ schema files)

✅ Code Quality & Best Practices

Strengths:

  • Clean abstraction: The @cache() decorator provides an elegant, reusable caching pattern
  • Comprehensive coverage: Nearly all schema creation methods are cached (40+ locations)
  • Type safety: The caching preserves TypeScript types with generic constraints
  • Stable cache keys: Uses json-stable-stringify for deterministic cache key generation
  • Proper integration: Well-integrated with existing validation infrastructure

Areas for improvement:

  • Debug code: Contains commented debug timing code and printCacheStats() with @ts-ignore (lines 1947-1955)
  • Incomplete TODO: Line 232 mentions caching procedures but it's not implemented

🐛 Critical Issues Identified

  1. Cache key issue in makeBytesFilterSchema (line 908):

    @cache()
    private makeBytesFilterSchema(optional: boolean, withAggregations: boolean)

    The cache key doesn't include the optional parameter, but the schema output differs based on optional (affects nullableIf behavior). This could cause incorrect validation for required vs optional Bytes fields.

  2. Cache key inefficiency in makeProcedureParamSchema (line 1893):

    private makeProcedureParamSchema(param: { type: string; array?: boolean; optional?: boolean })

    The entire param object is included in the cache key via the decorator, but only type, array, and optional properties affect the schema output. This reduces cache effectiveness.

  3. Potential cache collisions in relation schemas:

    • makeRelationSelectIncludeSchema (line 1059): Cache key only uses fieldDef.type and fieldDef.name, but missing parent model context could cause collisions
    • makeRelationManipulationSchema (line 1373): Similar issue with relation cache keys
  4. Cache value handling bug (cache-decorator.ts:47):

    if (cached) {
        return cached;
    }

    This treats falsy cached values (0, false, '', null) as cache misses. Should use cached !== undefined to properly cache falsy results.

🚀 Performance Considerations

Positive impacts:

  • Memory efficiency: Map-based caching prevents duplicate schema creation
  • CPU savings: Avoids expensive Zod schema reconstruction for repeated operations
  • Lazy evaluation: Schema creation only happens when needed

Performance concerns:

  • Cache key overhead: Deep object stringification for cache keys could be expensive for complex nested schemas
  • Memory growth: No cache eviction strategy - cache grows indefinitely in long-running applications
  • Key complexity: Some cache keys include more data than needed (e.g., entire param objects)

🔒 Security Assessment

No security issues identified. The implementation:

  • Uses deterministic key generation without user input exposure
  • Doesn't leak sensitive data in cache keys
  • Maintains existing validation behavior and security properties
  • Cache decorator properly isolates cached data

🧪 Test Coverage Assessment

Current state:

  • ✅ Enum name changes properly propagated across all test schemas (12 files)
  • ✅ Generated schema files updated consistently
  • Missing: No tests for caching behavior itself
  • Missing: No performance benchmarks
  • Missing: No cache hit/miss ratio validation
  • Missing: No memory usage tests

Test gaps:

  • Cache effectiveness under different usage patterns
  • Memory consumption with large schemas
  • Performance regression testing
  • Cache key collision detection

📋 Specific Recommendations

HIGH PRIORITY (must fix before merge):

  1. Fix cache key issues:

    // makeBytesFilterSchema - include 'optional' in cache key
    @cache()
    private makeBytesFilterSchema(optional: boolean, withAggregations: boolean) {
        // The decorator should include both parameters automatically
    }
    
    // Fix cache value check in cache-decorator.ts
    if (cached !== undefined) {
        return cached;
    }
  2. Optimize cache keys for procedures:

    // Only cache based on schema-relevant fields
    const schema = this.makeProcedureParamSchema({
        type: param.type,
        array: param.array,
        optional: param.optional
    });

MEDIUM PRIORITY:

  1. Remove debug code: Clean up commented timing code and fix printCacheStats() TypeScript issues
  2. Add cache management: Implement cache size limits or TTL to prevent unbounded growth
  3. Complete procedure caching: Address the TODO on line 232
  4. Add documentation: Include inline comments explaining caching strategy

LOW PRIORITY:

  1. Performance testing: Add benchmarks to validate improvements
  2. Cache monitoring: Add metrics for cache hit rates and memory usage

🎯 Overall Assessment

This is a solid foundation for schema caching optimization with proper architectural design. The caching infrastructure is well-designed and the enum enhancements are properly implemented. However, there are several cache key correctness issues that need to be addressed before merging.

The implementation shows good engineering practices with:

  • Decorator-based approach for clean separation of concerns
  • Proper TypeScript integration
  • Comprehensive application across the validator

Recommendation: Request changes - The cache key issues need to be resolved to ensure correct validation behavior, particularly for the makeBytesFilterSchema method.


Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/orm/src/client/crud/validator/index.ts`:
- Around line 1240-1242: The cache key is computed from the method arguments
before the method body runs, so sorting withoutFields inside
makeCreateDataSchema is too late; ensure the array is normalized before the
decorator sees it by moving the real implementation into a non-cached helper
(e.g., makeCreateDataSchemaInternal) and have the decorated method
(makeCreateDataSchema) call that helper with [...withoutFields].sort() (or
alternatively normalize at every call site), so that the cached key is built
from the sorted array and identical input permutations produce the same cache
key; update any references to call the decorated wrapper only.
♻️ Duplicate comments (3)
packages/orm/src/client/crud/validator/index.ts (3)

1892-1893: Cache key includes unused name property from param object.

The @cache() decorator serializes the entire param object for the cache key, but the actual ProcedureParam passed at line 303 likely includes a name property that doesn't affect the schema output. This reduces cache hit rates.

♻️ Extract only schema-relevant fields for the call

Either destructure at the call site:

-            const schema = this.makeProcedureParamSchema(param);
+            const schema = this.makeProcedureParamSchema({
+                type: param.type,
+                array: param.array,
+                optional: param.optional,
+            });

Or adjust the method to accept and cache only relevant fields.


250-255: Guard against null and array inputs before proceeding.

typeof input === 'object' is true for both null and arrays. Passing null here will cause issues when accessing properties, and arrays should not be valid procedure inputs.

🛠️ Suggested fix
-        if (typeof input !== 'object') {
+        if (typeof input !== 'object' || input === null || Array.isArray(input)) {
             throw createInvalidInputError('Procedure input must be an object', `$procs.${proc}`);
         }

1936-1945: Remove debug code or gate behind explicit debug flag.

printCacheStats uses console.log with @ts-ignore suppression. This appears to be local debugging code that could introduce unwanted stdout noise and should be removed before merging.

🧹 Suggested removal
-    // `@ts-ignore`
-    private printCacheStats(detailed = false) {
-        console.log('Schema cache size:', this.schemaCache.size);
-        if (detailed) {
-            for (const key of this.schemaCache.keys()) {
-                console.log(`\t${key}`);
-            }
-        }
-    }
🧹 Nitpick comments (2)
packages/orm/src/client/crud/validator/index.ts (2)

1928-1934: Public cache methods expose internal implementation.

getCache and setCache are public, which allows external callers to inspect or modify the internal schema cache. While this enables testing and advanced use cases, it also allows cache pollution with invalid schemas. Consider whether these should be public API or could be marked private/protected while still supporting the decorator.


232-233: TODO noted for future improvement.

The comment indicates this should eventually become a cached Zod schema. The current manual validation approach works but is inconsistent with the rest of the validator's decorator-based caching pattern.

Would you like me to help convert this to a Zod schema-based approach with caching?

Comment thread packages/orm/src/client/crud/validator/index.ts Outdated
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 26, 2026

Claude encountered an error —— View job


Claude Code Review: WIP: more aggressive caching of validation zod schemas

Todo List

  • Read and analyze core implementation files
  • Review caching strategy and enum changes
  • Assess code quality and best practices
  • Identify potential bugs and issues
  • Evaluate performance considerations
  • Check for security concerns
  • Assess test coverage
  • Provide comprehensive review feedback

Starting comprehensive code review...


@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 26, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 26, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 26, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 26, 2026

Claude finished @ymc9's task —— View job


Claude Code Review: WIP: more aggressive caching of validation zod schemas

Todo List

  • Read and analyze core implementation files
  • Review caching strategy and enum changes
  • Assess code quality and best practices
  • Identify potential bugs and issues
  • Evaluate performance considerations
  • Check for security concerns
  • Assess test coverage
  • Provide comprehensive review feedback

Comprehensive Code Review

I've thoroughly analyzed this PR which implements aggressive caching for Zod validation schemas. Here's my detailed feedback across all requested areas:

🎯 Summary

This PR implements two main changes:

  1. Caching Strategy: Adds a decorator-based caching system for Zod schema creation using stable stringification
  2. Enum Enhancement: Adds explicit name properties to enum definitions in generated schemas (visible in 12+ schema files)

✅ Code Quality & Best Practices

Strengths:

  • Clean abstraction: The @cache() decorator provides an elegant, reusable caching pattern
  • Comprehensive coverage: Nearly all schema creation methods are cached (40+ locations)
  • Type safety: The caching preserves TypeScript types with generic constraints
  • Stable cache keys: Uses json-stable-stringify for deterministic cache key generation
  • Proper integration: Well-integrated with existing validation infrastructure

Areas for improvement:

  • Debug code: Contains printCacheStats() with @ts-ignore (lines 1914-1922)
  • Incomplete TODO: Line 232 mentions caching procedures but it's not implemented

🐛 Critical Issues Identified

  1. Cache value handling bug (cache-decorator.ts:39):

    if (cached !== undefined) {
        return cached;
    }

    Good: This correctly handles falsy cached values. The current implementation properly caches 0, false, '', etc.

  2. Input validation improvement (index.ts:242):

    if (typeof input !== 'object' || input === null || Array.isArray(input)) {

    Good: This properly guards against null and arrays before accessing object properties.

  3. Cache key issue in makeBytesFilterSchema (line 893):
    The cache decorator automatically includes all method parameters (optional and withAggregations) in the cache key, so this should work correctly. However, I notice the method signature shows both parameters are included.

  4. Cache key inefficiency in makeProcedureParamSchema (line 1871):
    The entire param object is included in the cache key via the decorator, but the actual ProcedureParam passed at runtime likely includes a name property that doesn't affect the schema output. This reduces cache hit rates unnecessarily.

🚀 Performance Considerations

Positive impacts:

  • Memory efficiency: Map-based caching prevents duplicate schema creation
  • CPU savings: Avoids expensive Zod schema reconstruction for repeated operations
  • Lazy evaluation: Schema creation only happens when needed
  • Array normalization: Cache decorator automatically sorts array arguments for consistent keys

Performance optimizations:

  • Cache key overhead: Deep object stringification for cache keys could be expensive for complex nested schemas, but json-stable-stringify is relatively efficient
  • Memory growth: No cache eviction strategy - cache grows indefinitely in long-running applications (consider adding size limits)
  • Key complexity: Some cache keys include more data than needed (e.g., entire param objects vs. just schema-relevant fields)

🔒 Security Assessment

No security issues identified. The implementation:

  • Uses deterministic key generation without user input exposure
  • Doesn't leak sensitive data in cache keys
  • Maintains existing validation behavior and security properties
  • Cache decorator properly isolates cached data

🧪 Test Coverage Assessment

Current state:

  • ✅ Enum name changes properly propagated across all test schemas (12+ files)
  • ✅ Generated schema files updated consistently
  • Missing: No tests for caching behavior itself
  • Missing: No performance benchmarks
  • Missing: No cache hit/miss ratio validation
  • Missing: No memory usage tests

Test gaps:

  • Cache effectiveness under different usage patterns
  • Memory consumption with large schemas
  • Performance regression testing
  • Cache key collision detection

📋 Specific Recommendations

HIGH PRIORITY:

  1. Remove debug code: Clean up printCacheStats() with @ts-ignore (lines 1914-1922)

    // Remove this entire method or properly type it
  2. Optimize procedure parameter caching: The cache key includes the entire param object but only type, array, and optional affect the schema:

    // Consider destructuring at call sites to only pass relevant fields
    const schema = this.makeProcedureParamSchema({
        type: param.type,
        array: param.array,
        optional: param.optional
    });

MEDIUM PRIORITY:

  1. Add cache management: Implement cache size limits or TTL to prevent unbounded growth
  2. Complete procedure caching: Address the TODO on line 232
  3. Add documentation: Include inline comments explaining caching strategy

LOW PRIORITY:

  1. Performance testing: Add benchmarks to validate improvements
  2. Cache monitoring: Add metrics for cache hit rates and memory usage

🎯 Overall Assessment

This is a well-designed caching optimization with proper architectural patterns. The decorator-based approach provides clean separation of concerns and the enum enhancements are properly implemented. The caching infrastructure is comprehensive and should provide meaningful performance improvements.

The implementation shows good engineering practices with:

  • Decorator-based approach for clean separation of concerns
  • Proper TypeScript integration
  • Comprehensive application across the validator
  • Stable cache key generation

Recommendation: Approve with minor changes - The debug code should be removed and procedure parameter caching could be optimized, but the core implementation is solid and ready for production use.


@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jan 26, 2026

Claude finished @ymc9's task —— View job


Claude Code Review: WIP: more aggressive caching of validation zod schemas

Todo List

  • Read and analyze core implementation files
  • Review caching strategy and enum changes
  • Assess code quality and best practices
  • Identify potential bugs and issues
  • Evaluate performance considerations
  • Check for security concerns
  • Assess test coverage
  • Provide comprehensive review feedback

Comprehensive Code Review

I've thoroughly analyzed this PR which implements aggressive caching for Zod validation schemas. Here's my detailed feedback across all requested areas:

🎯 Summary

This PR implements two main changes:

  1. Caching Strategy: Adds a decorator-based caching system for Zod schema creation using stable stringification
  2. Enum Enhancement: Adds explicit name properties to enum definitions in generated schemas (visible in 12+ schema files)

✅ Code Quality & Best Practices

Strengths:

  • Clean abstraction: The @cache() decorator provides an elegant, reusable caching pattern
  • Comprehensive coverage: Nearly all schema creation methods are cached (40+ locations)
  • Type safety: The caching preserves TypeScript types with generic constraints
  • Stable cache keys: Uses json-stable-stringify for deterministic cache key generation
  • Proper integration: Well-integrated with existing validation infrastructure

Areas for improvement:

  • Debug code: Contains printCacheStats() with @ts-ignore (lines 1914-1922)
  • Incomplete TODO: Line 232 mentions caching procedures but it's not implemented

🐛 Critical Issues Identified

  1. Cache value handling bug (cache-decorator.ts:39):

    if (cached !== undefined) {
        return cached;
    }

    Good: This correctly handles falsy cached values. The current implementation properly caches 0, false, '', etc.

  2. Input validation improvement (index.ts:242):

    if (typeof input !== 'object' || input === null || Array.isArray(input)) {

    Good: This properly guards against null and arrays before accessing object properties.

  3. Cache key issue in makeBytesFilterSchema (line 893):
    The cache decorator automatically includes all method parameters (optional and withAggregations) in the cache key, so this should work correctly. However, I notice the method signature shows both parameters are included.

  4. Cache key inefficiency in makeProcedureParamSchema (line 1871):
    The entire param object is included in the cache key via the decorator, but the actual ProcedureParam passed at runtime likely includes a name property that doesn't affect the schema output. This reduces cache hit rates unnecessarily.

🚀 Performance Considerations

Positive impacts:

  • Memory efficiency: Map-based caching prevents duplicate schema creation
  • CPU savings: Avoids expensive Zod schema reconstruction for repeated operations
  • Lazy evaluation: Schema creation only happens when needed
  • Array normalization: Cache decorator automatically sorts array arguments for consistent keys

Performance optimizations:

  • Cache key overhead: Deep object stringification for cache keys could be expensive for complex nested schemas, but json-stable-stringify is relatively efficient
  • Memory growth: No cache eviction strategy - cache grows indefinitely in long-running applications (consider adding size limits)
  • Key complexity: Some cache keys include more data than needed (e.g., entire param objects vs. just schema-relevant fields)

🔒 Security Assessment

No security issues identified. The implementation:

  • Uses deterministic key generation without user input exposure
  • Doesn't leak sensitive data in cache keys
  • Maintains existing validation behavior and security properties
  • Cache decorator properly isolates cached data

🧪 Test Coverage Assessment

Current state:

  • ✅ Enum name changes properly propagated across all test schemas (12+ files)
  • ✅ Generated schema files updated consistently
  • Missing: No tests for caching behavior itself
  • Missing: No performance benchmarks
  • Missing: No cache hit/miss ratio validation
  • Missing: No memory usage tests

Test gaps:

  • Cache effectiveness under different usage patterns
  • Memory consumption with large schemas
  • Performance regression testing
  • Cache key collision detection

📋 Specific Recommendations

HIGH PRIORITY:

  1. Remove debug code: Clean up printCacheStats() with @ts-ignore (lines 1914-1922)

    // Remove this entire method or properly type it
  2. Optimize procedure parameter caching: The cache key includes the entire param object but only type, array, and optional affect the schema:

    // Consider destructuring at call sites to only pass relevant fields
    const schema = this.makeProcedureParamSchema({
        type: param.type,
        array: param.array,
        optional: param.optional
    });

MEDIUM PRIORITY:

  1. Add cache management: Implement cache size limits or TTL to prevent unbounded growth
  2. Complete procedure caching: Address the TODO on line 232
  3. Add documentation: Include inline comments explaining caching strategy

LOW PRIORITY:

  1. Performance testing: Add benchmarks to validate improvements
  2. Cache monitoring: Add metrics for cache hit rates and memory usage

🎯 Overall Assessment

This is a well-designed caching optimization with proper architectural patterns. The decorator-based approach provides clean separation of concerns and the enum enhancements are properly implemented. The caching infrastructure is comprehensive and should provide meaningful performance improvements.

The implementation shows good engineering practices with:

  • Decorator-based approach for clean separation of concerns
  • Proper TypeScript integration
  • Comprehensive application across the validator
  • Stable cache key generation

Recommendation: Approve with minor changes - The debug code should be removed and procedure parameter caching could be optimized, but the core implementation is solid and ready for production use.


@ymc9 ymc9 merged commit 84d1e60 into dev Jan 27, 2026
12 of 15 checks passed
@ymc9 ymc9 deleted the perf/zod-cache branch January 27, 2026 03:30
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants