一意IDが見た目より複雑な理由
データベースの行、APIリソース、セッショントークンに一意の識別子が必要です。簡単ですよね?数字を使えばいい。
連番整数の問題:予測可能(/users/1、/users/2)——誰でもリソースを列挙できます。中央機関が必要(「次の」番号を決めるのは1台のサーバーのみ)。そしてビジネス情報を漏洩する(1000番目の注文のIDは1000)。
そこで世界はより良いIDを発明した。そして発明し続けた。各フォーマットが実際に何をするかを解説します。
UUID(v4)——デフォルトの安全な選択肢
フォーマット: 550e8400-e29b-41d4-a716-446655440000
長さ: 36文字(32桁の16進数 + 4つのハイフン)
ランダム性: 122ビット
UUID v4は標準フォーマットの122ビットランダムデータです。衝突確率は天文学的に低く(50%の衝突確率を得るには、毎秒10億個のUUIDを85年間生成する必要がある)、事実上不可能です。
UUIDが得意なこと:
- 普遍的な標準——すべての言語、データベース、フレームワークがネイティブサポート
- 調整不要——どのサーバーやクライアントでも独立して生成可能
- 非連続——列挙攻撃なし
UUIDが苦手なこと:
- ソート不可——UUIDはランダムなので作成時刻順にソートされません。Bツリーインデックス(ほとんどのデータベースの仕組み)では、ランダムな挿入が「ページ分割」を引き起こし、データベースが常にインデックスを再編成します。大規模ではコストが高い。
- 大きい:文字列として36文字、バイナリで16バイト
- URLフレンドリーでない(ハイフンを含む)
UUID v4を使う場面: ソート順を気にせず、広くサポートされた標準IDが必要なとき。
UUID v7——修正版UUID
フォーマット: 018e2c4c-3d12-7f3a-91f8-3e4a5b6c7d8e
長さ: 36文字
ランダム性: 74ビット(48ビットのミリ秒タイムスタンププレフィックス付き)
UUID v7(2023年批准)はタイムスタンププレフィックス付きのUUIDです。最初の48ビットはミリ秒単位のUnixタイムスタンプで、UUIDを作成時刻でソート可能にします。
なぜ重要か: ソート可能なID = Bツリーへの連続挿入 = 大規模でのデータベースインデックスパフォーマンスが大幅向上。
UUID v7を使う場面: UUID互換性が必要だが、データベースパフォーマンスのために時間順のIDが必要なとき。
ULID——ソート可能でURLセーフなUUID代替
フォーマット: 01ARZ3NDEKTSV4RRFFQ69G5FAV
長さ: 26文字
ランダム性: 80ビット(48ビットのミリ秒タイムスタンププレフィックス付き)
ULID(Universally Unique Lexicographically Sortable Identifier)は、よりクリーンなフォーマットでUUIDのソート問題を解決します。48ビットのタイムスタンプ + 80ビットのランダム性をCrockford Base32でエンコード(ハイフンなし、曖昧な文字なし)。
ULIDが得意なこと:
- 辞書順でソート可能(文字列として正しくソート)
- URLセーフ(ハイフンや特殊文字なし)
- 26文字 vs UUIDの36文字——よりコンパクト
- ミリ秒精度のタイムスタンプを内包
ULIDが苦手なこと:
- UUIDほど普遍的でない——ほとんどの言語でライブラリが必要
- 単調性:同一ミリ秒内で生成された複数のULIDは、単調バリアントなしでは正しくソートされない場合がある
ULIDを使う場面: UUID互換性不要で、ソート可能かつコンパクトでURLセーフなIDが必要なとき。
CUID2——URLセーフ、衝突耐性、タイムスタンプなし
フォーマット: clyg4v5l20000356ok1f5t6nb
長さ: 24文字(デフォルト)
ランダム性: 高(SHA-3フィンガープリント、予測可能な構造なし)
CUID2はセキュリティ敏感なコンテキスト向けに設計されています。ULIDと異なり、意図的にタイムスタンププレフィックスがありません——IDからリソースの作成時刻を推測できません。
CUID2が得意なこと:
- 公開IDとしてUUID/ULIDより安全(タイミング情報なし)
- URLセーフ
- 設定可能な長さ(長さと衝突耐性のトレードオフ)
CUID2が苦手なこと:
- ソート不可(設計上)
- UUIDほど広くサポートされていない
- 特定ライブラリに依存
CUID2を使う場面: IDが公開されており、作成タイムスタンプを漏洩したくないとき(ユーザーID、APIキー、短縮リンク)。
NanoID——小さく、速く、カスタマイズ可能
フォーマット: V1StGXR8_Z5jdHi6B-myT
長さ: 21文字(デフォルト、設定可能)
アルファベット: カスタマイズ可能(デフォルト:URLセーフBase64)
NanoIDはUUIDの現代的な軽量代替です。21文字でUUID v4と同じ衝突確率を持ち、よりコンパクトでカスタマイズ可能なアルファベット付き。
NanoIDが得意なこと:
- 最もコンパクト(21文字 vs UUIDの36文字)
- カスタマイズ可能なアルファベット——小文字のみ、数字のみなどのIDを生成可能
- 20以上の言語で利用可能
- 高速
NanoIDが苦手なこと:
- ソート不可
- 標準ではない(RFC なし)
NanoIDを使う場面: サイズが重要なとき(URL、短いトークン)やカスタムアルファベットが必要なとき。
決定テーブル
| UUID v4 | UUID v7 | ULID | CUID2 | NanoID | |
|---|---|---|---|---|---|
| ソート可能 | ✗ | ✓ | ✓ | ✗ | ✗ |
| URLセーフ | ✗ | ✗ | ✓ | ✓ | ✓ |
| 標準(RFC) | ✓ | ✓ | ✗ | ✗ | ✗ |
| DB性能 | 悪い | 良い | 良い | 悪い | 悪い |
| タイムスタンプ非公開 | ✓ | ✗ | ✗ | ✓ | ✓ |
| サイズ(文字) | 36 | 36 | 26 | 24 | 21 |
シンプルな答え
- デフォルトの選択: UUID v7——ソート可能、標準、DB性能良好
- URLセーフ + ソート可能が必要: ULID
- 公開ID(タイミング非公開): CUID2
- 短いトークン、カスタムアルファベット: NanoID
- レガシーシステム / 最大互換性: UUID v4
今すぐIDを生成
UUIDジェネレーターでUUID v4とv7を生成——一括生成、ワンクリックコピー。アカウント不要。