← Semua picks

Format Compare Recommended

Zod vs Valibot vs ArkType: validation library 2026

Zod sudah dominate validation di TS ecosystem. Valibot 90% lebih kecil. ArkType TypeScript-first dengan syntax di-string. Saya pakai keduanya, verdict berbeda.

18 April 2026 · 8 menit
ZodValibotArkType

TL;DR

  • Zod 4: Recommended sebagai default. Ecosystem terbesar, dokumentasi sempurna, battle-tested.
  • Valibot: Recommended untuk bundle-size-critical (browser-first, edge function dengan size limit).
  • ArkType: Watch — promising, tapi syntax less familiar untuk TS dev.

Konteks

Pakai keduanya di production:

  • Zod: 5 project, semua server-side validation
  • Valibot: 2 project, browser-first (form validation client)
  • ArkType: 1 project eksperimen (tidak production)

Bundle size comparison

Schema simple: object dengan 5 field, mix of string, number, email, enum.

LibraryBundle size (minified+gzipped)
Zod 412.8 KB
Valibot1.4 KB
ArkType4.2 KB

Valibot 9x lebih kecil dari Zod. ArkType 3x lebih kecil.

Untuk server-side: bundle size tidak critical (server load once). Untuk client-side: matter untuk LCP/FID di mobile.

Syntax comparison

Zod

import { z } from 'zod';

const userSchema = z.object({
  name: z.string().min(2).max(50),
  email: z.string().email(),
  age: z.number().int().positive().max(150),
  role: z.enum(['admin', 'user', 'guest']),
  phone: z.string().regex(/^08\d{8,11}$/, 'Nomor HP Indonesia tidak valid'),
});

type User = z.infer<typeof userSchema>;

const result = userSchema.safeParse(data);
if (result.success) {
  console.log(result.data);
} else {
  console.log(result.error.issues);
}

Valibot

import * as v from 'valibot';

const userSchema = v.object({
  name: v.pipe(v.string(), v.minLength(2), v.maxLength(50)),
  email: v.pipe(v.string(), v.email()),
  age: v.pipe(v.number(), v.integer(), v.minValue(1), v.maxValue(150)),
  role: v.picklist(['admin', 'user', 'guest']),
  phone: v.pipe(v.string(), v.regex(/^08\d{8,11}$/, 'Nomor HP Indonesia tidak valid')),
});

type User = v.InferOutput<typeof userSchema>;

const result = v.safeParse(userSchema, data);
if (result.success) {
  console.log(result.output);
} else {
  console.log(result.issues);
}

Valibot pakai pipe + function-per-validation approach (similar to RxJS pipe). Lebih verbose dari Zod tapi bundle bisa tree-shake (cuma include validation yang Anda pakai).

ArkType

import { type } from 'arktype';

const userSchema = type({
  name: 'string > 2 & < 50',
  email: 'string.email',
  age: 'number.integer >= 1 & <= 150',
  role: "'admin' | 'user' | 'guest'",
  phone: 'string.regex /^08\\d{8,11}$/',
});

type User = typeof userSchema.infer;

const result = userSchema(data);
if (result instanceof type.errors) {
  console.log(result.summary);
} else {
  console.log(result);
}

ArkType pakai string-based DSL. Familiar bagi TypeScript user (sintaks mirip TS type), tapi error message string-based bisa fragile.

Performance

Validation 100,000 objects (5 field each):

LibraryTime
Zod 4380ms
Valibot240ms
ArkType180ms

ArkType paling cepat (compile-time optimization). Valibot 2x lebih cepat dari Zod. Zod slowest tapi acceptable.

Untuk server validation 10-100 request/detik, semua acceptable. Untuk client form validation (1-10 validation/detik), tidak ada matter.

Yang Zod menang

Ecosystem

Zod has integration dengan:

  • React Hook Form (@hookform/resolvers/zod)
  • TanStack Form
  • tRPC (default schema)
  • Astro Action (default schema sejak v6)
  • Drizzle ORM (drizzle-zod)
  • OpenAPI (zod-to-openapi)
  • ts-rest, ts-morph, dll

Setiap library TS yang butuh schema → support Zod first.

Mature error handling

Zod 4 errors API powerful:

const result = userSchema.safeParse(data);
if (!result.success) {
  // Format error per field
  result.error.format();
  // Flatten ke object simple
  result.error.flatten();
  // Custom format
  result.error.issues.map((i) => ({ path: i.path, message: i.message }));
}

Refinement & transformation

const passwordSchema = z.string()
  .min(8)
  .refine((s) => /\d/.test(s), { message: 'Butuh angka' })
  .refine((s) => /[A-Z]/.test(s), { message: 'Butuh huruf besar' });

const dateSchema = z.string().transform((s) => new Date(s));

Valibot punya equivalent (check, transform) tapi syntax lebih verbose.

Documentation

Zod docs adalah gold standard. Cover edge case, contoh real-world, migration guide.

Yang Valibot menang

Bundle size

1.4 KB vs Zod 12.8 KB. Untuk client-side form yang pakai 3-5 validation, Valibot save 11 KB.

Untuk landing page yang LCP target < 1.5s, tiap KB matter.

Tree-shaking

Karena Valibot function-based, bundler bisa tree-shake validation yang tidak Anda pakai. Zod is monolithic — semua atau none.

// Hanya import yang Anda pakai
import { object, string, email, minLength } from 'valibot';

Final bundle Anda only includes ini, tidak number, array, union, dll yang tidak terpakai.

Edge function size

Cloudflare Workers limit 1MB compressed bundle. Untuk Workers yang berat (banyak validation + ORM + auth), saving bundle space matter.

Yang ArkType menang

Performance

2x faster than Zod karena compile-time optimization. Untuk server yang validate 10K request/detik, ini matter.

Syntax familiar bagi TS dev

'string > 2 & < 50' mirip TypeScript type. Easy to read kalau Anda already familiar dengan TS.

Type inference excellent

ArkType inference type tighter dari Zod dalam beberapa edge case (e.g., template literal type, conditional type).

Yang ArkType kurang

Syntax less mainstream

Walaupun familiar bagi TS dev, syntax DSL ini mean:

  • Error message kurang clear (string parsing error vs structured error)
  • Refactoring tools (VS Code rename, find references) kadang miss DSL string
  • Plugin/integration ecosystem kecil

Documentation less polished

ArkType docs OK tapi tidak sekomprehensif Zod. Examples less, edge case kurang dokumentasi.

Smaller community

GitHub issues, Stack Overflow questions, blog post — Zod has 10-50x lebih banyak. Saat Anda stuck, harder to find help dengan ArkType.

Decision matrix

Use caseRecommended
Server-side validation (API)Zod (default)
Form validation client-sideValibot
Edge function dengan size limitValibot
Performance-critical validation (10K+ req/s)ArkType
Beginner / first validation libraryZod
Monorepo dengan multiple integrationZod
Sole project, optimize bundleValibot

Konteks Indonesia

Untuk SMB Indonesia API server: Zod adalah default safe. Integration dengan Astro Action, tRPC, Drizzle, dll smooth.

Untuk SMB Indonesia client form yang LCP critical: Valibot save 11KB. Untuk landing page yang sudah optimize lain, 11KB worth — bisa improve LCP 50-150ms di 4G connection.

Untuk SMB Indonesia high-throughput API (jarang use case): ArkType untuk performance, Zod untuk ecosystem balance.

Yang surprising

Saya thought Valibot adalah “Zod alternative untuk size purist”. Setelah pakai 2 project, saya temukan Valibot lebih cocok untuk form validation specifically karena pattern function compose work well dengan React Hook Form / TanStack Form.

Zod lebih cocok untuk API contract (server side, full schema, transformation, complex refinement).

Bisa pakai keduanya di same project: Valibot client-side, Zod server-side. Saya sudah pakai di 1 project, work fine.

Migration

Zod → Valibot

// Before (Zod)
const schema = z.object({
  name: z.string().min(2),
  age: z.number().int().positive(),
});

// After (Valibot)
const schema = v.object({
  name: v.pipe(v.string(), v.minLength(2)),
  age: v.pipe(v.number(), v.integer(), v.minValue(1)),
});

Mechanical conversion. Time: 1-2 jam untuk 20-30 schema.

Caveat: integration library (React Hook Form resolver) butuh switch dari @hookform/resolvers/zod ke @hookform/resolvers/valibot.

Verdict

Recommended:

  • Zod 4 sebagai default untuk most TS project Indonesia
  • Valibot untuk client-side form atau edge function

Watch:

  • ArkType kalau performance jadi bottleneck (rare untuk SMB)

Konteks praktis untuk SMB yang juga butuh local presence: panduan setup GBP untuk SMB Tangerang.

Ditulis oleh Asti Larasati

// Pick Format Compare lain


← Semua picks RSS feed