Zod v3 vs v4 パフォーマンス検証|公式の「14倍高速」は本当か?

開発

Zod v4 がリリースされ、公式は「14倍高速」「バンドルサイズ57%削減」と発表しています。Hacker News で 782 ポイントを獲得するほど注目されていますが、実際のところどうなのでしょうか?

正直なところ、公式の数字をそのまま信じていいのか気になったので、自分で検証してみました。結論から言うと、公式発表は概ね正確でした。ただし、バンドルサイズにはバンドラー選択という落とし穴がありました。Zod でフロントエンド/バックエンドのバリデーションを一元管理している方も多いと思うので、この検証結果は参考になるはずです。

検証環境

まず、今回の検証環境を共有しておきます。

MacBook Pro M1 Pro
Node.js v22.21.1
zod v3.23.8
zod v4.0.0
mitata v1.0.34(高精度ベンチマーク)
esbuild v0.24.0 / Rolldown(バンドルサイズ計測)

パース速度のベンチマークには、公式と同じmitataライブラリを使用しました。mitata は V8 エンジンの JIT コンパイラ最適化を考慮した高精度ベンチマークツールで、ウォームアップや統計的な外れ値除去を自動で行います。Bun や Deno の公式ベンチマークでも採用されています。

パース速度の検証結果

実測値と公式発表の比較

公式と同じ mitata を使ってベンチマークを取った結果がこちらです。

テスト実測値公式発表判定
文字列パース16x高速14x高速公式より良い
配列パース3.8x高速7x高速差あり
オブジェクトパース6.0x高速6.5x高速ほぼ一致

文字列パースは公式発表を上回る16倍という結果が出ました。オブジェクトパースも 6.0 倍で公式の 6.5 倍とほぼ一致しています。

開発環境に近い計測(tsx実行)

mitata は JIT 最適化を最大限に引き出す設計のため、本番環境に近い数値が出ます。一方、多くの開発者が日常的に使う tsx での計測結果も参考になります。

テストtsx実行mitata
文字列パース4.1x16xJIT最適化の影響大
数値パース4.4x--
配列パース3.2x3.8xほぼ同等
オブジェクト(単純)5.6x6.0xほぼ同等
オブジェクト(複雑)1.7x-複雑なスキーマは改善率低下
Union型3.5x--
Optional/Nullable2.2x--
Transform3.3x--

tsx 実行での平均は約3.5倍の高速化です。開発中に体感できる速度改善としては、この数字が現実的な目安になります。

計測方法による差の理由

mitata と tsx で差が出る理由は、JIT コンパイラの最適化です。

  • mitata: 同じコードを繰り返し実行し、JIT が最大限に最適化された状態で計測
  • tsx: TypeScript をトランスパイルしながら実行するため、JIT 最適化が十分に効かない

本番環境(ビルド済み JS)では mitata に近い数値が期待できます。開発中は tsx に近い体感になるでしょう。

パフォーマンス改善は本物

どちらの計測方法でも、v4 が確実に速くなっているのは事実です。公式発表は「最適化された条件での最大値」と理解しておけば、期待を裏切られることはありません。

TypeScript型チェックの改善

パース速度よりも体感しやすいのが、TypeScript の型チェック速度の改善です。

公式によると、同じコードをコンパイルした場合:

  • v3: 25,000 以上の型インスタンス生成
  • v4: 約 175 の型インスタンス生成

これは140倍以上の削減です。実際、複雑な Zod スキーマを持つプロジェクトでは、IDE のレスポンスが明らかに改善されます。

// このようなチェーンが多いプロジェクトで効果大
const schema = z.object({
  user: z.object({
    profile: z.object({
      settings: z.object({
        // 深いネストでも型推論が軽い
      })
    })
  })
});

VSCode で「型推論が重い」と感じていた人は、v4 への移行でかなり改善するはずです。

バンドルサイズの落とし穴

ここからが重要な話です。公式は「バンドルサイズ57%削減」と発表していますが、これはバンドラーによって結果が大きく異なります

バンドラー別の実測結果

バンドラーZod v3Zod v4Zod v4 mini
esbuild13.5 KB60.5 KB54.9 KB
Rolldown13.2 KB14.9 KB3.8 KB

※ すべて gzipped サイズ

esbuild では v4 が 4.5 倍大きくなりました。一方、Rolldown では v4 mini が 3.8 KBと、公式発表の 3.94 KB とほぼ一致しています。

なぜバンドラーで差が出るのか

v4 のアーキテクチャには「並列宣言」という仕組みがあります。例えばZodMiniString$ZodStringを継承する形で実装されており、esbuild では tree-shaking がうまく効きません。

これは GitHub の Issue #4637 で報告されている既知の問題で、CommonJS として使う場合は特に影響が大きく、AWS Lambdaのコールドスタートが24〜48%遅くなったという報告もあります。

解決策: Rolldownを使う

公式の数字を再現するには、Rolldown を使うのが最も確実です。

# Rolldownのインストール
npm install -D rolldown

Rolldown は Vite の次期バンドラーとして開発されており、tree-shaking の精度が高いのが特徴です。

esbuildを使い続ける場合

esbuild から移行できない場合は、以下の方法で影響を軽減できます。

Zod miniを使う

// これを
import { z } from 'zod';

// こう変える
import { z } from 'zod/mini';

esbuild でも mini を使うことで、フル版よりは若干小さくなります(60.5 KB → 54.9 KB)。

ESMを使う

CommonJS より ESM 形式の方が tree-shaking が効きやすいです。

// package.json
{
  "type": "module"
}

v3から移行すべきか?

結論として、移行はおすすめです。ただし条件付きで。

移行をおすすめするケース

状況理由
パース速度を改善したい文字列16倍、オブジェクト6倍の高速化
IDEが重い型チェック140倍改善
Rolldown / Vite を使っているminiで3.8KB、十分軽い
新機能を使いたいz.interface()、JSON Schema変換など

慎重になるべきケース

状況理由
esbuild から移行できないバンドルサイズが4.5倍に増加
AWS Lambda(CommonJS)コールドスタート悪化の可能性
安定性最優先v3は枯れている

段階的移行が可能

Zod v4 はzod/v3パスで旧バージョンも提供しています。これを使えば、同じプロジェクト内で v3 と v4 を併存させながら段階的に移行できます。

// 既存コードはv3のまま
import { z } from 'zod/v3';

// 新しいコードはv4で書く
import { z as z4 } from 'zod';

検証コード

今回使用したベンチマークコードを公開しておきます。自分の環境でも試してみてください。

import { z as z3 } from 'zod3';  // npm:zod@3.23.8
import { z as z4 } from 'zod';   // zod@4.0.0

const ITERATIONS = 100_000;
const WARMUP = 1_000;

function bench(fn: () => void, iterations: number): number {
  // ウォームアップ
  for (let i = 0; i < WARMUP; i++) fn();

  const start = performance.now();
  for (let i = 0; i < iterations; i++) fn();
  return performance.now() - start;
}

// 文字列パース
const stringSchema3 = z3.string();
const stringSchema4 = z4.string();

const v3Time = bench(() => stringSchema3.parse('hello'), ITERATIONS);
const v4Time = bench(() => stringSchema4.parse('hello'), ITERATIONS);

console.log(`v3: ${v3Time}ms, v4: ${v4Time}ms`);
console.log(`高速化率: ${(v3Time / v4Time).toFixed(1)}x`);

package.json の設定:

{
  "type": "module",
  "dependencies": {
    "zod": "^4.0.0",
    "zod3": "npm:zod@3.23.8"
  }
}

まとめ

Zod v4 のパフォーマンス検証をまとめると:

公式発表検証結果
文字列14倍高速正確(16倍確認)
配列7倍高速やや過大(3.8倍確認)
オブジェクト6.5倍高速正確(6.0倍確認)
バンドル57%削減条件付き(Rolldown必須)
  • パース速度: 公式発表は概ね正確。文字列 16 倍、オブジェクト 6 倍の高速化を確認
  • 型チェック: 140倍以上の改善、IDE が重い人には特に効果的
  • バンドルサイズ: バンドラー選択が重要。esbuild では 4.5 倍増加、Rolldown + mini なら 3.8 KB
  • 移行判断: Rolldown / Vite ユーザーは移行推奨、esbuild / Lambda は慎重に

公式の数字は「Rolldown を使った場合」という前提があることを理解しておけば、v4 への移行は安心しておすすめできます。新規プロジェクトなら迷わず v4 を選んでください。

Thanks for reading!
ZodTypeScriptパフォーマンスベンチマークバリデーション