Pourquoi les identifiants uniques sont plus complexes qu'ils n'y paraissent
Tu as besoin d'un identifiant unique pour une ligne en base de données, une ressource API, un token de session. Simple, non ? Utilise juste un nombre.
Le problème avec les entiers séquentiels : ils sont prévisibles (/users/1, /users/2) — n'importe qui peut énumérer tes ressources. Ils nécessitent une autorité centrale (un seul serveur peut décider du "prochain" nombre). Et ils révèlent des infos business (ta 1000ème commande a l'ID 1000).
Le monde a donc inventé de meilleures solutions. Puis n'a pas arrêté d'en inventer. Voici ce que chacun fait réellement.
UUID (v4) — La valeur sûre par défaut
Format : 550e8400-e29b-41d4-a716-446655440000
Longueur : 36 caractères (32 hex + 4 tirets)
Aléatoire : 122 bits
UUID v4 est 122 bits aléatoires formatés de façon standard. La probabilité de collision est si astronomiquement faible (il faudrait générer 1 milliard d'UUID par seconde pendant 85 ans pour avoir 50% de chance de collision) qu'elle est pratiquement impossible.
Ce qu'UUID fait bien :
- Standard universel — chaque langage, base de données et framework a un support natif
- Aucune coordination nécessaire — n'importe quel serveur, n'importe quel client peut en générer un indépendamment
- Non séquentiel — pas d'attaques par énumération
Ce qu'UUID fait mal :
- Non triable — les UUID sont aléatoires, donc ils ne se trient pas par ordre de création. Dans un index B-tree (comment fonctionnent la plupart des bases de données), les insertions aléatoires causent des "page splits" — la base réorganise constamment son index. À grande échelle, c'est coûteux.
- Grand : 36 chars en string, 16 bytes en binaire
- Pas URL-friendly (contient des tirets)
Utiliser UUID v4 quand : tu as besoin d'un ID standard et largement supporté, sans te soucier de l'ordre de tri.
UUID v7 — UUID corrigé
Format : 018e2c4c-3d12-7f3a-91f8-3e4a5b6c7d8e
Longueur : 36 caractères
Aléatoire : 74 bits (avec préfixe timestamp 48 bits en millisecondes)
UUID v7 (ratifié en 2023) est UUID avec un préfixe timestamp. Les 48 premiers bits sont un timestamp Unix en millisecondes, rendant les UUID triables par ordre de création.
Pourquoi c'est important : IDs triables = insertions séquentielles dans le B-tree = performances d'index bien meilleures à grande échelle.
Utiliser UUID v7 quand : tu veux la compatibilité UUID mais tu as besoin d'IDs ordonnés dans le temps pour les performances en base.
ULID — Alternative UUID triable et URL-safe
Format : 01ARZ3NDEKTSV4RRFFQ69G5FAV
Longueur : 26 caractères
Aléatoire : 80 bits (avec préfixe timestamp 48 bits en millisecondes)
ULID (Universally Unique Lexicographically Sortable Identifier) résout le problème de tri d'UUID avec un format plus propre. Il encode 48 bits de timestamp + 80 bits d'aléatoire en Crockford Base32 (sans tirets, sans caractères ambigus).
Ce qu'ULID fait bien :
- Triable lexicographiquement (tri correct en tant que string)
- URL-safe (pas de tirets ni caractères spéciaux)
- 26 chars vs 36 pour UUID — plus compact
- Timestamp en précision milliseconde embarqué
Ce qu'ULID fait mal :
- Moins universel qu'UUID — nécessite une bibliothèque dans la plupart des langages
- Monotonie : plusieurs ULID générés dans la même milliseconde peuvent ne pas se trier correctement sans la variante monotone
Utiliser ULID quand : tu veux des IDs triables qui sont aussi compacts et URL-safe, sans besoin de compatibilité UUID.
CUID2 — URL-safe, résistant aux collisions, sans timestamp
Format : clyg4v5l20000356ok1f5t6nb
Longueur : 24 caractères (par défaut)
Aléatoire : élevé (fingerprinting SHA-3, pas de structure prévisible)
CUID2 est conçu pour les contextes sensibles à la sécurité. Contrairement à ULID, il n'a délibérément pas de préfixe timestamp — impossible de déduire quand une ressource a été créée à partir de son ID.
Ce que CUID2 fait bien :
- Plus sécurisé qu'UUID/ULID pour les IDs publics (pas d'info de timing)
- URL-safe
- Longueur configurable (compromis entre longueur et résistance aux collisions)
Ce que CUID2 fait mal :
- Non triable (par conception)
- Moins largement supporté qu'UUID
- Dépend d'une bibliothèque spécifique
Utiliser CUID2 quand : les IDs sont publics et tu ne veux pas révéler les timestamps de création (IDs utilisateur, clés API, liens courts).
NanoID — Petit, rapide, personnalisable
Format : V1StGXR8_Z5jdHi6B-myT
Longueur : 21 caractères (par défaut, configurable)
Alphabet : personnalisable (par défaut : Base64 URL-safe)
NanoID est une alternative moderne et légère à UUID. Même probabilité de collision qu'UUID v4 en 21 chars, mais plus petit et avec un alphabet personnalisable.
Ce que NanoID fait bien :
- Le plus compact (21 chars vs 36 pour UUID)
- Alphabet personnalisable — peut générer des IDs en minuscules uniquement, chiffres uniquement, etc.
- Disponible en 20+ langages
- Rapide
Ce que NanoID fait mal :
- Non triable
- Pas un standard (pas de RFC)
Utiliser NanoID quand : la taille compte (URLs, tokens courts) ou tu as besoin d'un alphabet personnalisé.
Tableau de décision
| UUID v4 | UUID v7 | ULID | CUID2 | NanoID | |
|---|---|---|---|---|---|
| Triable | ✗ | ✓ | ✓ | ✗ | ✗ |
| URL-safe | ✗ | ✗ | ✓ | ✓ | ✓ |
| Standard (RFC) | ✓ | ✓ | ✗ | ✗ | ✗ |
| Perf. DB | Mauvaise | Bonne | Bonne | Mauvaise | Mauvaise |
| Cache le timestamp | ✓ | ✗ | ✗ | ✓ | ✓ |
| Taille (chars) | 36 | 36 | 26 | 24 | 21 |
La réponse simple
- Choix par défaut : UUID v7 — triable, standard, bonnes performances DB
- Besoin URL-safe + triable : ULID
- IDs publics (ne pas révéler le timing) : CUID2
- Tokens courts, alphabet personnalisé : NanoID
- Système legacy / compatibilité maximale : UUID v4
Génère des IDs maintenant
Générateur UUID génère des UUID v4 et v7 — génération en masse, copie en un clic. Aucun compte requis.