2026-06-17 · 7 min
Zod v5 vs Valibot vs ArkType: 3 Bulan di Form Production
Tiga bulan lalu saya audit bundle size SaaS klien Jakarta. Zod kontribusi 38KB ke client bundle. Saya kepo apakah Valibot atau ArkType bisa kasih saving meaningful. Saya migrate satu modul ke tiap-tiap library, observe selama 90 hari. Hasil terukur.
Setup
Modul yang di-migrate: form invoice creation di SaaS B2B (~28 field, nested objects, conditional validation). Yang sudah pakai Zod baseline.
Yang saya bandingkan:
- Zod v5 (yang sudah dipakai)
- Valibot 1.0 (modular, tree-shakeable)
- ArkType 2.0 (TypeScript syntax based)
Skenario test:
- Bundle size client (gzipped)
- Parse performance (validate single object)
- Inference quality di IDE
- Error message quality untuk end-user
Bundle size
Saya pakai webpack bundle analyzer, ukur kontribusi library + schema definition:
Zod v5:
- Library: 24KB gzipped (core + common)
- Schema definition (28 field nested): 4KB
- Total: 28KB
Valibot 1.0 (modular import):
import { object, string, number, email } from 'valibot';
- Library: 3.5KB gzipped (only used parsers)
- Schema definition: 5KB
- Total: 8.5KB
ArkType 2.0:
- Library: 14KB gzipped
- Schema definition: 3KB
- Total: 17KB
Valibot menang besar. 3.3x lebih kecil dari Zod. Untuk client-side bundle: signifikan, terutama di mobile.
Parse performance
Benchmark dengan 100,000 parse iteration object 28-field nested.
Zod v5: 380ms total (~3.8 microsecond per parse) Valibot 1.0: 220ms total (~2.2 microsecond per parse) ArkType 2.0: 145ms total (~1.45 microsecond per parse)
ArkType 2.6x lebih cepat dari Zod. Valibot 1.7x lebih cepat.
Untuk single form submit: irrelevant (semua sub-millisecond). Untuk batch validation di data import (kasus klien: import 5000 customer CSV): 380ms vs 145ms — perceivable.
DX: schema definition
Zod v5:
const invoiceSchema = z.object({
customer_name: z.string().min(2).max(100),
email: z.string().email(),
items: z.array(z.object({
name: z.string(),
quantity: z.number().positive(),
price: z.number().positive(),
})).min(1),
notes: z.string().optional(),
});
Familiar, chainable, banyak helper. Untuk junior dev: paling mudah dipahami.
Valibot 1.0:
import { object, string, array, number, email, minLength, maxLength, pipe } from 'valibot';
const invoiceSchema = object({
customer_name: pipe(string(), minLength(2), maxLength(100)),
email: pipe(string(), email()),
items: pipe(
array(object({
name: string(),
quantity: pipe(number(), minValue(0.01)),
price: pipe(number(), minValue(0.01)),
})),
minLength(1)
),
notes: optional(string()),
});
Pipe pattern explicit. Functional style. Lebih verbose tapi tree-shakeable.
ArkType 2.0:
import { type } from 'arktype';
const invoiceSchema = type({
customer_name: 'string > 2 <= 100',
email: 'string.email',
items: type({
name: 'string',
quantity: 'number > 0',
price: 'number > 0',
}, '>=', 1),
'notes?': 'string',
});
Sangat compact. String-based DSL. Mirroring TS type syntax. Powerful, tapi learning curve untuk team baru.
Error message untuk end-user
Zod v5: error message generic by default (“Required”, “Invalid email”). Customizable per field. Saya pakai .message() chain untuk Indonesian: z.string({ message: "Wajib diisi" }).
Valibot 1.0: similar pattern, message dari parameter di parser:
string("Wajib diisi"), email("Format email salah")
ArkType 2.0: error message dari schema constraints, lebih sulit di-customize. Saya butuh wrapper untuk localize.
Untuk SaaS Indonesia yang error message harus dalam Bahasa Indonesia: Zod paling clean experience. Valibot OK. ArkType butuh extra work.
Inference quality
Saya test inference di VSCode dengan complex generic:
Zod v5: excellent. z.infer<typeof schema> works flawlessly even untuk deeply nested.
Valibot 1.0: excellent. Input<typeof schema> works.
ArkType 2.0: excellent. Type instant tanpa generic wrapper.
Semua tie di sini. Modern TS validator landscape semua solid inference.
Migration cost
Zod → Valibot: setiap chained validator harus jadi pipe(...). Tools ada? Saya tulis codemod sendiri. 6 jam untuk migrate 23 schema. Test coverage rescue dari regression.
Zod → ArkType: rewrite schema syntax fully. ~12 jam untuk 23 schema. Harder karena DSL berbeda paradigm.
Saya rekomendasi: Valibot kalau saving bundle penting. ArkType kalau performance hot loop matter.
Ecosystem & integration
Zod: ekosistem ter-luas. Integration:
- tRPC (default)
- React Hook Form (zodResolver)
- Astro Actions (
astro:schemare-export Zod) - Drizzle (drizzle-zod adapter)
- OpenAPI (zod-to-openapi)
Valibot: ekosistem growing.
- React Hook Form (valibot resolver)
- Astro Actions: butuh adapter custom (saya tulis 30-line helper)
- tRPC: bisa pakai valibot di v11
- Drizzle: tidak ada adapter official, harus custom
ArkType: ekosistem kecil.
- React Hook Form: butuh manual integration
- Astro Actions: tidak ada adapter
- tRPC: butuh adapter
Untuk project dengan banyak integration tooling: Zod menang clear.
Verdict per use case
SaaS web Indonesia dengan banyak form (kasus klien saya): Zod v5. Ekosistem + DX worth marginal bundle cost.
Mobile web / edge function dengan bundle critical: Valibot. Saving 20KB bundle = first-paint lebih cepat di Indonesia 3G.
Data pipeline / batch processing intensive: ArkType. Performance gain matter pada volume tinggi.
Backend Node server tanpa client constraint: Zod. Bundle size irrelevant, DX win.
Apa yang akhirnya saya pakai
Klien SaaS saya: tetap Zod v5. Saving bundle 20KB tidak justify migration effort + ecosystem retraining team.
Untuk MVP baru (kasus 3-hari MVP saya) dengan target mobile-first Indonesia user di 3G: saya start Valibot fresh.
Bukan magic — semua 3 library solid. Pilih berdasarkan constraint (bundle, perf, ekosistem), bukan hype. Saya udah hindari migrate semua kompleks demi 20KB saving. Time-value not worth it untuk app desktop-heavy.
Ditulis oleh Reza Pradipta