Porting Zod to C#: ZodSharp – A Zero-Allocation, High-Performance Schema Validation Library for .NET
As a .NET developer, I’ve long been frustrated by one persistent pain point: most validation libraries rely heavily on reflection, leading to slow performance and constant allocations. Whether it’s validating API inputs, forms, or data pipelines, that overhead adds up — especially in high-throughput scenarios.
Then I discovered Zod — the gold standard for schema validation in the TypeScript world, created by colinhacks. Its fluent API, full type inference, excellent error messages, and zero-dependency design made it feel like magic. But there was nothing quite like it in C#.
So I decided to change that. I built ZodSharp — a complete, from-scratch rewrite of Zod tailored for modern .NET, with a relentless focus on performance, zero-allocation, and developer experience.
This post is the story of that journey and why ZodSharp might just become your new go-to validation library.
Why Zod Became the Standard in TypeScript
Zod dominates the JS/TS ecosystem for good reason:
- Fluent, chainable API that's a joy to write
- Full type safety with automatic inference
- Powerful composition for complex schemas
- Rich transforms and refinements
- Clear, structured error reporting
- Zero runtime dependencies
In .NET, we have solid options like FluentValidation, but they lean on reflection and expressions — great for flexibility, but costly in performance-critical paths.
ZodSharp brings that same elegant developer experience to C# — without the allocation tax.
Not a Simple Port — A Performance-First Rewrite
While staying faithful to Zod’s public API and semantics, nearly every internal detail was re-engineered for .NET’s strengths.
Zero-Allocation: The Core Design Goal
The #1 priority: validation should produce zero garbage in hot paths.
Reflection-based validation creates objects, closures, and temporary collections on every call. ZodSharp eliminates that entirely.
Key techniques:
- Validation rules as structs
public readonly struct MinLengthRule : IValidationRule<string>
{
private readonly int _min;
public MinLengthRule(int min) => _min = min;
public bool IsValid(in string value) => value.Length >= _min;
}
Immutable collections with minimal overhead (
ImmutableArray,ImmutableDictionary)ValidationResult as a struct — no heap allocation on success or failure
ArrayPool for any temporary buffers
Manual loops instead of LINQ in performance-critical sections
Span and ReadOnlySpan for string operations with zero copies
Fluent API — As Close to Zod as Possible
The API feels instantly familiar to Zod users:
// Almost identical to Zod TS
var schema = Z.String()
.Min(3)
.Max(50)
.Email()
.Trim()
.ToLower();
Object schemas:
var userSchema = Z.Object()
.Field("name", Z.String().Min(1))
.Field("age", Z.Number().Min(0).Max(120))
.Field("email", Z.String().Email())
.Build();
Transforms, refinements, unions, optionals, literals — all supported.
Source Generators & DataAnnotations Integration
One of the biggest .NET-specific wins: compile-time schema generation.
Decorate a class with [ZodSchema] and use standard DataAnnotations — ZodSharp generates a static schema at build time:
[ZodSchema]
public class User
{
[Required, StringLength(50, MinimumLength = 3)]
public string Name { get; set; } = string.Empty;
[Range(0, 120)]
public int Age { get; set; }
[EmailAddress]
public string Email { get; set; } = string.Empty;
}
// Usage
var result = UserSchema.Validate(new User { ... });
No runtime reflection needed.
Project Architecture Overview
ZodSharp/
├── src/ZodSharp/
│ ├── Core/ → Interfaces, base classes, results, errors
│ ├── Schemas/ → String, Number, Object, Array, Union, etc.
│ ├── Rules/ → Struct-based validation rules
│ ├── Expressions/ → Compiled validators via Expression Trees
│ ├── Json/ → Newtonsoft.Json integration
│ ├── Optimizations/ → Zero-allocation helpers
│ └── Z.cs → Static factory (Z.String(), Z.Object(), etc.)
├── src/ZodSharp.SourceGenerators/
│ └── ZodSchemaGenerator.cs → [ZodSchema] source generator
├── example/ → Full usage samples
└── README.md
Rough Performance Wins
Early benchmarks show dramatic improvements over typical reflection-based validation:
| Scenario | Reflection-Based | ZodSharp | Gain |
|---|---|---|---|
| Simple string validation | ~0.15 ms | ~0.01 ms | ~15× faster |
| Complex object validation | ~0.8 ms | ~0.05 ms | ~16× faster |
| Allocations per validation | Multiple | Zero | Eliminated |
The gap widens under load.
Practical Use Cases
ZodSharp shines anywhere validation performance matters:
- High-throughput APIs (REST, gRPC, GraphQL)
- Microservices with frequent input validation
- Real-time systems
- Data ingestion pipelines
- Desktop/mobile apps with complex forms
- Anywhere you want Zod-like DX without the runtime cost
What’s Already Implemented
- Fluent schema building
- Full primitive support (string, number, boolean, array, object, union, literal)
- Transforms (
.Trim(),.ToLower(), etc.) - Refinements (custom validation)
- Optional / nullable wrappers
- Discriminated unions
- Lazy/recursive schemas
- Source generator with DataAnnotations
- Newtonsoft.Json integration
- Advanced string rules (
.Url(),.Uuid(),.Email(),.StartsWith()...) - Advanced number rules (
.Positive(),.MultipleOf(),.Finite()...)
What’s Next?
- Public benchmark suite
- ASP.NET Core model binding integration
- Entity Framework validation hooks
- More JSON serializer support (System.Text.Json)
- Enhanced error formatting
- Community contributions!
Final Thoughts
Building ZodSharp was incredibly rewarding. It wasn’t just about bringing Zod to C# — it was about solving a real, widespread pain in the .NET ecosystem: fast, type-safe, zero-overhead validation.
If you’ve ever groaned at reflection slowdowns or wished for a more modern validation experience in C#, I hope you’ll give ZodSharp a try.
GitHub: https://github.com/guinhx/ZodSharp
NuGet: https://www.nuget.org/packages/ZodSharp
Original Zod: https://github.com/colinhacks/zod
Feedback, stars, issues, and PRs are very welcome! Let me know — have you felt the reflection validation pain? What would make you switch?
Thanks for reading! 🚀
Tags: #dotnet #csharp #validation #zod #performance #opensource #typesafety
Top comments (0)