Contexto
Bundle mínimo virou um objetivo de design explícito para bibliotecas mais novas do ecossistema TypeScript, e Valibot é o exemplo mais direto disso na validação de schema — nascida como uma resposta ao peso de bibliotecas mais antigas como Zod, ainda que hoje as duas cubram o mesmo terreno de funcionalidades. A raiz da diferença está na unidade básica de composição: Zod expõe um schema builder único: você parte de z.object({...}) ou de um schema primitivo como z.string() e encadeia métodos (.min(), .optional()) no mesmo objeto. Valibot quebra cada validação em uma função independente e importável separadamente, combinadas explicitamente através de v.pipe(...) — não existe um objeto central acumulando métodos, existe uma sequência de funções que o pipe executa em ordem.
Essa granularidade é a razão de existir do Valibot: nasceu depois de Zod, com bundle mínimo como objetivo de design desde o início, apostando que separar cada validador em uma função isolada permite que builds modernos removam do bundle final qualquer validador que o código não importa explicitamente. Os dois, no entanto, resolvem o mesmo conjunto de problemas do dia a dia — validação de formulários, parsing de payload de API, checagem de variáveis de ambiente — e produzem mensagens de erro estruturadas que dá para mapear para o formato que a aplicação precisar.
Quando escolher Zod
Zod é a escolha mais segura quando o time quer o ecossistema mais maduro e o menor atrito de integração — a grande maioria das bibliotecas que aceitam "um schema de validação" como parâmetro (formulários, geração de tipos para API, ferramentas de schema para agentes) suporta Zod nativamente ou como a opção mais testada.
import { z } from "zod";
const Signup = z.object({
email: z.email(),
password: z.string().min(8),
});
Repare que z.email() acima já é, por si só, um schema completo — não precisa ser envolvido em nada para ser usado como validador de e-mail. Esse formato de "schema builder único" é o modelo mental com o qual a maior parte do ecossistema TypeScript já está acostumada, o que reduz a curva de aprendizado para quem já usou qualquer versão de Zod antes. O lado menos favorável é que, por ser uma biblioteca única e mais estabelecida, Zod historicamente carrega mais código no bundle final do que uma abordagem pensada desde o início para granularidade máxima.
Quando escolher Valibot
Valibot faz sentido quando o peso do bundle de validação importa de verdade — aplicações que rodam em edge functions com limite de tamanho de pacote, ou frontends com orçamento de performance apertado, onde cada KB de JavaScript carregado tem custo mensurável:
import * as v from "valibot";
const Signup = v.object({
email: v.pipe(v.string(), v.email()),
password: v.pipe(v.string(), v.minLength(8)),
});
Diferente do z.email() do Zod, o v.email() acima é uma ação de validação — ela só existe dentro de um pipe(), nunca sozinha como schema. Essa granularidade é deliberada: como cada validador é uma função separada, um bundler moderno consegue remover do pacote final qualquer validador que o código nunca importa, algo mais difícil de fazer quando os validadores são métodos de um único objeto schema. O custo é a verbosidade — cada validação de formato de string precisa do pipe() explícito — e um ecossistema de integrações ainda em crescimento, comparado à cobertura já consolidada de Zod nas bibliotecas mais usadas do dia a dia. Essa verbosidade ao menos é previsível: o padrão pipe(tipo(), regra1(), regra2()) se repete de forma consistente em qualquer validação de string, número ou array, sem exceções de sintaxe para memorizar caso a caso.
Veredito
O peso em KB que Valibot economiza só compensa quando alguém de fato mede o orçamento de bundle do projeto — fora esse cenário específico, a maturidade de ecossistema que Zod acumulou pesa mais na balança. Se o time prioriza o ecossistema mais maduro e integrações já testadas na maioria das bibliotecas populares, e não tem uma restrição de bundle particularmente apertada, Zod é a opção com menos atrito. Se o projeto roda em um ambiente sensível a tamanho de pacote — edge functions, aplicações com orçamento de performance rígido — e o time aceita a verbosidade extra de compor cada validação via pipe(), Valibot foi desenhado exatamente para esse cenário.
O fiel da balança tende a se mover sozinho com o tempo: conforme mais bibliotecas do ecossistema TypeScript passarem a suportar Valibot nativamente, a vantagem de maturidade que hoje pesa a favor de Zod fica menor a cada nova integração — mas essa mudança ainda não chegou à escala que Zod já alcançou.