Skip to main content

Superstruct vs Zod in 2026: Lightweight vs Feature-Rich Validation

·PkgPulse Team

TL;DR

Zod for most projects; Superstruct when bundle size is critical. Superstruct (~2M weekly downloads) is ~7KB gzipped and has a simple functional API. Zod (~20M downloads) is ~28KB but has richer built-in validators, better ecosystem integration, and more active development. For most web apps, Zod's size difference is negligible. For edge functions or browser bundles where every KB matters, Superstruct is worth evaluating.

Key Takeaways

  • Zod: ~20M weekly downloads — Superstruct: ~2M (npm, March 2026)
  • Superstruct: ~7KB gzipped — Zod: ~28KB gzipped
  • Superstruct uses plain functions — no method chaining (different style)
  • Zod has better TypeScript inference — Superstruct types require manual casting
  • Zod is much more actively maintained — more contributors, faster releases

API Style

// Zod — method chains, OOP-ish API
import { z } from 'zod';

const User = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().positive(),
  tags: z.array(z.string()).optional(),
});

const result = User.safeParse(data);
if (result.success) {
  const user = result.data; // Typed as { name: string; email: string; ... }
}
// Superstruct — functional API, plain composable functions
import { object, string, number, array, optional, min, max, integer, positive } from 'superstruct';

const User = object({
  name: string(),   // min/max need to be added separately (custom types)
  email: string(),  // No built-in .email() — add custom refinement
  age: integer(),   // positive() refinement
  tags: optional(array(string())),
});

const [error, value] = User.try(data);
// value is Infer<typeof User> = { name: string; email: string; ... }

Superstruct's functional style is composable but has fewer built-in validators. Zod's method chain style feels more natural to TypeScript developers.


Bundle Size

Library       | Minified+Gzip | Note
--------------|---------------|------
Superstruct   | ~7KB          | Minimal, tree-shakeable
Valibot       | ~8KB          | Functional, tree-shakeable
ArkType       | ~10KB         | TypeScript-native syntax
Zod v4        | ~28KB         | Full-featured
Joi           | ~45KB         | JavaScript-first, largest

For comparison: React is ~40KB gzipped

For a typical SaaS web app, the size difference between Superstruct and Zod is negligible (21KB in a >500KB bundle). It matters for:

  • Edge functions with tight cold-start requirements
  • Browser-only bundles on low-bandwidth targets
  • Libraries that ship validation to users (don't want to impose large deps)

Custom Types

// Superstruct — custom types via refinement
import { refine, string } from 'superstruct';

const Email = refine(string(), 'Email', (value) => {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
    || `Expected an email but got "${value}"`;
});

const PositiveNumber = refine(number(), 'PositiveNumber', (value) => {
  return value > 0 || `Expected a positive number but got ${value}`;
});
// Zod — built-in types for common validations
z.string().email()       // Built in
z.string().url()         // Built in
z.string().uuid()        // Built in
z.number().positive()    // Built in
z.number().int()         // Built in

// Custom refinement when needed:
z.string().refine(
  (val) => isValidUsername(val),
  { message: 'Invalid username format' }
);

Transformation

// Superstruct — coerce utility
import { create, string, number } from 'superstruct';
const coerced = create('42', number()); // Throws if can't coerce

// Or use coerce() for default transformations:
import { coerce, defaulted } from 'superstruct';
const NumberFromString = coerce(number(), string(), (value) => parseFloat(value));
// Zod — transform built into schemas
const FormData = z.object({
  age: z.string().transform(Number),    // String → Number
  date: z.string().transform(s => new Date(s)),  // String → Date
  name: z.string().trim().toLowerCase(), // Chain transforms
});

When to Choose

Choose Zod when:

  • Standard web application development
  • Using React Hook Form, tRPC, or Drizzle (native integrations)
  • Bundle size isn't a constraint
  • Richer built-in validators save time
  • Team productivity over raw performance

Choose Superstruct when:

  • Library author who doesn't want to impose large dependency on users
  • Edge function bundle size is critical
  • Functional composition style is preferred
  • You need a lightweight validation baseline with custom extensions

The reality: for 95% of web development, Zod is the better choice. Superstruct's advantage is real but situational.


Compare Superstruct and Zod package health on PkgPulse.

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.