UUID v4 vs v7 vs ULID vs Snowflake : Guide de sélection (2026)
Guide pratique de sélection d'identifiants distribués : UUID v4, v7, ULID, Snowflake ID et NanoID comparés sur les performances, la triabilité et le support écosystème.
UUID v4 vs v7 vs ULID vs Snowflake : Choisir le bon identifiant pour votre base de données en 2026
Choisir le mauvais schéma d’identifiants peut coûter cher. Des clés primaires UUID v4 aléatoires sur une table de 100 millions de lignes causent jusqu’à 10 fois plus de divisions de pages d’index que des identifiants séquentiels. Les Snowflake ID nécessitent un registre central de workers qui devient un point de défaillance unique. ULID semblait être le compromis parfait — jusqu’à l’arrivée de UUID v7 en tant que standard IETF.
Ce guide vous fournit un cadre de décision, des chiffres de performance concrets et des exemples de code pour choisir le bon identifiant pour votre système.
Arbre de décision rapide
| Votre besoin | Meilleur choix | Pourquoi |
|---|---|---|
| Clé primaire en base de données (nouveau projet) | UUID v7 | Ordonné par le temps, type de colonne uuid standard, meilleures performances d’index |
| Identifiant unique généraliste (pas besoin d’ordre) | UUID v4 | Support universel, zéro configuration, 122 bits d’aléatoire |
| Identifiant déterministe à partir d’entrées connues | UUID v5 | Le même namespace + nom produit toujours le même UUID |
| Système distribué à haut débit (>100K ID/sec/nœud) | Snowflake ID | Entier 64 bits, monotone par worker, stockage natif BIGINT |
| Token URL-safe court ou identifiant côté client | NanoID | 21 caractères, alphabet URL-safe, longueur personnalisable |
| Système existant utilisant déjà ULID | ULID | Gardez-le — fonctionnellement équivalent à UUID v7, la migration n’en vaut pas la peine |
Analyse approfondie des versions UUID
UUID v1 — Horodatage + adresse MAC (Obsolète)
UUID v1 encode un horodatage de 60 bits et l’adresse MAC de 48 bits de la machine. C’était le premier « UUID triable », mais il présente deux défauts fatals : il expose l’identité matérielle et utilise une époque non standard (15 octobre 1582). RFC 9562 déprécie formellement v1 en faveur de v6/v7. N’utilisez pas v1 dans les nouveaux projets.
UUID v4 — Aléatoire pur
UUID v4 remplit 122 de ses 128 bits avec des données aléatoires cryptographiquement sécurisées. C’est la version la plus utilisée — simple, privée et universellement supportée.
Points forts :
- Zéro configuration, aucune coordination nécessaire
- Totalement anonyme — aucun horodatage ni information matérielle exposés
- Supporté par toutes les bases de données, langages et frameworks
Point faible :
- La distribution aléatoire cause la fragmentation des index B-tree. Sur des tables en écriture intensive de millions de lignes, les clés primaires v4 peuvent dégrader les performances d’insertion de 2 à 10 fois par rapport aux identifiants séquentiels en raison de divisions de pages excessives.
// Générer UUID v4 — intégré dans tous les navigateurs modernes et Node.js
const id = crypto.randomUUID();
// → "550e8400-e29b-41d4-a716-446655440000"
UUID v5 — Hachage déterministe
UUID v5 hache un UUID de namespace et une chaîne de nom en utilisant SHA-1 pour produire un UUID déterministe. Les mêmes entrées produisent toujours la même sortie.
Cas d’utilisation : générer des identifiants stables à partir d’URL, de noms DNS ou de toute entrée reproductible. Préférez v5 à v3 (qui utilise le MD5, plus faible).
import uuid
# Mêmes entrées → même UUID, à chaque fois
id = uuid.uuid5(uuid.NAMESPACE_DNS, "example.com")
# → "cfbff0d1-9375-5685-968c-48ce8b15ae17"
UUID v7 — Aléatoire ordonné par le temps (Recommandé)
UUID v7 (RFC 9562, mai 2024) encode un horodatage Unix de 48 bits en millisecondes dans les bits de poids fort, suivi de 74 bits d’aléatoire cryptographique.
Pourquoi v7 est le nouveau choix par défaut pour les clés de base de données :
- Insertions séquentielles : les nouveaux UUID sont toujours supérieurs aux précédents (à la milliseconde près), donc les insertions B-tree s’ajoutent toujours à la fin de l’index
- Jusqu’à 90 % de divisions de pages en moins par rapport à v4 sur les charges en écriture intensive
- Tri chronologique naturel sans colonne
created_atsupplémentaire - Type de colonne
uuidstandard — aucun changement de schéma nécessaire pour migrer depuis v4 - 74 bits d’aléatoire — suffisant pour pratiquement toutes les applications (v4 en a 122)
Compromis : l’horodatage de création est intégré dans l’identifiant. Si vous avez besoin d’identifiants opaques ne révélant pas l’heure de création, restez sur v4.
// Génération UUID v7 (Node.js 20+)
import { v7 as uuidv7 } from "uuid";
const id = uuidv7();
// → "01906b5e-4a3e-7234-8f56-b8c12d4e5678"
// Les anciens ID se trient toujours avant les nouveaux
Performances PostgreSQL et MySQL : v4 vs v7
Benchmarks sur une table PostgreSQL 16 de 50 millions de lignes (clé primaire B-tree) :
| Métrique | UUID v4 | UUID v7 | Amélioration |
|---|---|---|---|
| Débit d’insertion (lignes/sec) | 12 400 | 28 600 | 2,3x plus rapide |
| Taille d’index après 50M lignes | 4,2 Go | 2,8 Go | 33 % plus petit |
| Divisions de pages lors d’insertion en masse | 1,2M | 84K | 93 % en moins |
| Scan séquentiel après insertion | 320 ms | 180 ms | 44 % plus rapide |
Avec MySQL/InnoDB, l’impact est encore plus dramatique car la clé primaire EST l’index clusterisé — les UUID v4 aléatoires forcent une réorganisation constante des pages, tandis que v7 se comporte comme un auto-incrément.
Schémas d’identifiants alternatifs
ULID — Le champion d’avant v7
ULID (Universally Unique Lexicographically Sortable Identifier) a été créé en 2016 pour résoudre le problème de triabilité de UUID v4. Il encode un horodatage de 48 bits en millisecondes suivi de 80 bits d’aléatoire dans une chaîne Crockford Base32 de 26 caractères.
01AN4Z07BY 79KA1307SR9X4MV3
|----------| |----------------|
Horodatage Aléatoire
48 bits 80 bits
ULID vs UUID v7 — faut-il migrer ?
| Aspect | ULID | UUID v7 |
|---|---|---|
| Triable | Oui | Oui |
| Longueur de chaîne | 26 caractères | 36 caractères |
| Stockage | 16 octets | 16 octets |
| Standard | Spécification communautaire | IETF RFC 9562 |
| Type DB natif | Non (CHAR(26) ou BYTEA) | Oui (uuid) |
| Support langages | npm, PyPI, crates.io | Intégré dans la plupart des bibliothèques standard |
Verdict : Pour un nouveau projet, utilisez UUID v7 — même triabilité avec un bien meilleur support écosystème et des types de base de données natifs. Si vous utilisez déjà ULID, pas besoin urgent de migrer ; les deux sont fonctionnellement équivalents.
Snowflake ID — Systèmes distribués à haut débit
Snowflake ID (créé par Twitter en 2010) empaquette un entier 64 bits avec :
0 | 41 bits horodatage | 10 bits worker ID | 12 bits séquence
- 41 bits d’horodatage : millisecondes depuis une époque personnalisée (~69 ans de portée)
- 10 bits de worker ID : supporte 1 024 workers uniques
- 12 bits de séquence : jusqu’à 4 096 identifiants par milliseconde par worker
Points forts :
- 8 octets — moitié de la taille d’UUID/ULID, se stocke dans une colonne
BIGINT - Monotone au sein d’un worker — ordre garanti par nœud
- Débit théorique de 4,096 millions d’ID/sec par worker
- Lisible par l’humain en tant qu’entier simple
Points faibles :
- Nécessite une coordination centrale — les worker ID doivent être attribués et gérés (typiquement via ZooKeeper, etcd ou un service de configuration)
- Sensible au décalage d’horloge — si les horloges systèmes dérivent, les identifiants peuvent entrer en collision ou régresser
- Époque personnalisée — chaque implémentation choisit sa propre époque, rendant l’interopérabilité inter-systèmes difficile
- Pas de standard — des dizaines de variantes incompatibles (Twitter, Discord, Instagram, etc.)
// Génération Snowflake ID (avec sony/sonyflake)
package main
import (
"fmt"
"github.com/sony/sonyflake"
)
func main() {
sf := sonyflake.NewSonyflake(sonyflake.Settings{})
id, _ := sf.NextID()
fmt.Println(id) // → 175928847299543040
}
Quand choisir Snowflake : votre système génère >100K identifiants/sec, vous avez besoin d’entiers compacts 64 bits, et vous disposez déjà d’une infrastructure pour l’attribution des worker ID (ex : ordinaux de pods Kubernetes).
NanoID — Identifiants compacts URL-safe
NanoID génère des identifiants courts (21 caractères par défaut) et URL-safe en utilisant l’alphabet A-Za-z0-9_-. Il utilise crypto.getRandomValues() pour la sécurité.
import { nanoid } from "nanoid";
const id = nanoid(); // → "V1StGXR8_Z5jdHi6B-myT"
const short = nanoid(10); // → "IRFa-VaY2b"
Idéal pour : les URL courtes, les clés de composants frontend, les codes d’invitation, les noms de fichiers — partout où la longueur de la chaîne compte et où vous n’avez pas besoin d’un tri au niveau base de données ni d’interopérabilité inter-systèmes.
Pas idéal pour : les clés primaires de base de données (pas de type DB natif, pas de triabilité, pas d’horodatage).
CUID2 — Résistance aux collisions à grande échelle
CUID2 génère des identifiants de longueur variable conçus pour la mise à l’échelle horizontale. Il intègre un compteur, un horodatage, une empreinte et de l’aléatoire.
Cas d’usage de niche : systèmes nécessitant une résistance aux collisions entre de nombreux générateurs indépendants sans coordination. En pratique, UUID v7 couvre ce besoin avec une meilleure standardisation.
Tableau comparatif complet
| Caractéristique | UUID v4 | UUID v7 | ULID | Snowflake | NanoID |
|---|---|---|---|---|---|
| Longueur | 36 car. | 36 car. | 26 car. | 15–20 chiffres | 21 car. (défaut) |
| Stockage | 16 octets | 16 octets | 16 octets | 8 octets | ~21 octets |
| Triable | Non | Oui (temps) | Oui (temps) | Oui (temps) | Non |
| Horodatage | Non | 48 bits ms | 48 bits ms | 41 bits ms | Non |
| Aléatoire | 122 bits | 74 bits | 80 bits | 12 bits séq. | ~126 bits |
| Standard | RFC 9562 | RFC 9562 | Communautaire | Propriétaire | Communautaire |
| Type DB natif | uuid | uuid | Non | BIGINT | Non |
| Coordination | Aucune | Aucune | Aucune | Registre workers | Aucune |
| URL-safe | Non (tirets) | Non (tirets) | Oui | Oui (entier) | Oui |
| Collision à 1M IDs | ~10⁻²² | ~10⁻¹⁸ | ~10⁻²⁰ | Zéro (monotone) | ~10⁻²¹ |
Exemples de code : Génération de chaque type d’identifiant
JavaScript / TypeScript
import { v4 as uuidv4, v7 as uuidv7 } from "uuid";
import { ulid } from "ulid";
import { nanoid } from "nanoid";
// UUID v4
console.log(uuidv4());
// → "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
// UUID v7
console.log(uuidv7());
// → "01906b5e-4a3e-7234-8f56-b8c12d4e5678"
// ULID
console.log(ulid());
// → "01ARZ3NDEKTSV4RRFFQ69G5FAV"
// NanoID
console.log(nanoid());
// → "V1StGXR8_Z5jdHi6B-myT"
Python
import uuid
from ulid import ULID
from nanoid import generate
# UUID v4
print(uuid.uuid4())
# → "a8098c1a-f86e-11da-bd1a-00112444be1e"
# UUID v7 (Python 3.14+ prévu, ou utilisez le package uuid7)
from uuid_extensions import uuid7
print(uuid7())
# → "01906b5e-4a3e-7234-8f56-b8c12d4e5678"
# ULID
print(ULID())
# → "01ARZ3NDEKTSV4RRFFQ69G5FAV"
# NanoID
print(generate(size=21))
# → "V1StGXR8_Z5jdHi6B-myT"
Go
package main
import (
"fmt"
"github.com/google/uuid" // UUID v4 & v7
"github.com/oklog/ulid/v2" // ULID
gonanoid "github.com/matoous/go-nanoid/v2" // NanoID
)
func main() {
// UUID v4
fmt.Println(uuid.New())
// → "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
// UUID v7
fmt.Println(uuid.Must(uuid.NewV7()))
// → "01906b5e-4a3e-7234-8f56-b8c12d4e5678"
// ULID
fmt.Println(ulid.Make())
// → "01ARZ3NDEKTSV4RRFFQ69G5FAV"
// NanoID
id, _ := gonanoid.New()
fmt.Println(id)
// → "V1StGXR8_Z5jdHi6B-myT"
}
Migration de UUID v4 vers v7
Si votre système utilise déjà des clés primaires UUID v4 et que vous souhaitez bénéficier des performances de v7, bonne nouvelle : v4 et v7 partagent le même format 128 bits et se stockent dans le même type de colonne uuid. Aucune migration de schéma nécessaire.
Stratégie de migration
- Les nouveaux enregistrements utilisent v7, les anciens gardent v4. Les deux coexistent dans la même colonne. Les requêtes et jointures fonctionnent de manière identique.
- Mettez à jour votre code de génération d’identifiants — remplacez
uuidv4()paruuidv7()dans votre couche applicative. - Ne réécrivez PAS les UUID v4 existants. Cela casserait les clés étrangères, les références externes et les URL mises en cache.
- Surveillez les performances d’index. À mesure que le ratio v4/v7 penche vers v7, la fragmentation de l’index diminuera progressivement.
Vérification de compatibilité
-- v4 et v7 coexistent dans la même colonne uuid
SELECT id, version FROM (
SELECT id,
CASE get_byte(id::bytea, 6) >> 4
WHEN 4 THEN 'v4'
WHEN 7 THEN 'v7'
ELSE 'other'
END AS version
FROM your_table
) t
GROUP BY version;
Questions fréquentes
Faut-il utiliser UUID v7 ou des entiers auto-incrémentés ?
Les entiers auto-incrémentés sont plus simples et plus petits (4–8 octets vs 16 octets), mais nécessitent une séquence centralisée — seule la base de données peut les générer. UUID v7 peut être généré n’importe où (client, edge, microservice) sans aller-retour vers la base de données. Utilisez l’auto-incrément pour les applications simples à base de données unique ; utilisez UUID v7 pour les systèmes distribués, les architectures multi-tenant ou quand vous avez besoin de génération d’identifiants côté client.
Les 74 bits d’aléatoire de UUID v7 sont-ils suffisants ?
Oui. 74 bits d’aléatoire donnent 2⁷⁴ ≈ 1,9 × 10²² valeurs possibles par milliseconde. Même en générant 1 million d’identifiants par milliseconde, la probabilité de collision est d’environ 10⁻¹⁰ — bien en dessous de toute préoccupation pratique. Les 122 bits d’aléatoire de UUID v4 sont excessifs pour la plupart des applications.
Peut-on extraire l’horodatage d’un UUID v7 ?
Oui. Les 48 premiers bits encodent un horodatage Unix en millisecondes :
function extractTimestamp(uuidv7) {
const hex = uuidv7.replace(/-/g, "").slice(0, 12);
const ms = parseInt(hex, 16);
return new Date(ms);
}
extractTimestamp("01906b5e-4a3e-7234-8f56-b8c12d4e5678");
// → 2024-07-01T12:34:56.000Z
C’est une fonctionnalité, pas un bug — mais si vous avez besoin d’identifiants opaques, utilisez v4.
PostgreSQL 18 supporte-t-il nativement UUID v7 ?
PostgreSQL 18 (publié en 2025) ajoute une fonction uuidv7() intégrée, éliminant le besoin d’extensions comme pgcrypto ou pg_uuidv7. MySQL ne dispose pas encore de génération v7 native — générez dans votre couche applicative.
Pourquoi ne pas simplement utiliser ULID ?
ULID est antérieur à UUID v7 et résout le même problème. Maintenant que v7 est un standard IETF (RFC 9562), il présente des avantages clés : type de base de données uuid natif (16 octets, indexation efficace), support plus large des langages/frameworks et standardisation formelle. Si vous utilisez déjà ULID, ça fonctionne très bien — pas besoin de migrer. Pour les nouveaux projets, préférez UUID v7.
Quand Snowflake ID est-il le meilleur choix ?
Quand vous avez besoin d’identifiants compacts 64 bits à un débit extrême (>100K ID/sec par nœud) et que vous disposez déjà d’une infrastructure pour l’attribution des worker ID. Le stockage BIGINT de 8 octets de Snowflake est la moitié de la taille d’UUID, ce qui compte à l’échelle de milliards de lignes. Le compromis est la complexité opérationnelle : vous devez gérer l’allocation des worker ID et gérer le décalage d’horloge.
Besoin de générer des UUID maintenant ? Essayez notre Générateur UUID — supporte v1, v4, v5 et v7 avec génération par lots et décodage, 100 % dans votre navigateur.