03 / GUIDES
UUID vs ULID : choisir des identifiants pour votre application
UUID v4 contre v7, structure et triabilité de l'ULID, ce que les identifiants aléatoires font à un index B-tree, probabilité de collision, exposition dans les URL, et génération d'identifiants en local.
Ce qu'un identifiant applicatif doit faire
Un identifiant généré a un travail — être unique — plus quelques autres ramassés en chemin : se générer partout sans coordination, se stocker compactement, se trier de façon prévisible, et ne rien fuiter d'embarrassant. UUID et ULID franchissent tous deux la barre de l'unicité ; ils diffèrent sur tout le reste.
- Sans coordinationGénération décentralisée : tout service, worker ou onglet de navigateur peut frapper un identifiant sans demander à un compteur central, ce qui rend les deux formats adaptés aux systèmes distribués.
- Mêmes 128 bits128 bits dans les deux cas : un UUID est une valeur de 128 bits écrite en 36 caractères hexadécimaux avec tirets ; un ULID porte les mêmes 128 bits en 26 caractères base32.
- L'agencement fait la différenceLa vraie question est l'agencement : quels bits sont aléatoires et lesquels encodent le temps décide du comportement de l'identifiant dans un index et de ce qu'il révèle.
Versions d'UUID : v4 est aléatoire, v7 est ordonné dans le temps
La RFC 9562 définit plusieurs versions d'UUID, mais deux dominent le travail applicatif. La version 4 remplit 122 des 128 bits d'aléa et n'embarque rien d'autre ; la version 7 ouvre avec un horodatage Unix de 48 bits en millisecondes et remplit les 74 bits restants d'aléa.
- v4 : pur aléatoirev4 est le choix maximal pour la vie privée : la valeur ne dit rien de quand ni où elle a été faite, et 122 bits aléatoires sont plus d'unicité qu'aucune application ne dépensera jamais.
- v7 : le temps d'abordv7 se trie d'abord selon son horodatage à la milliseconde. L'ordre au sein d'une même milliseconde et entre appareils dépend du générateur et des horloges.
- Zapper v1Les versions plus anciennes sont héritées : v1 embarquait une adresse MAC et une valeur d'horloge, fuitant les deux ; v3 et v5 sont des hachages à base de nom pour dériver des ID stables, pas de l'aléa frais.
ULID : triable et compact en texte
Un ULID fait 26 caractères de base32 Crockford : les 10 premiers caractères encodent un horodatage en millisecondes de 48 bits, les 16 restants encodent 80 bits aléatoires. L'alphabet exclut délibérément I, L, O et U : les identifiants survivent à une lecture à voix haute ou à une frappe depuis une capture d'écran.
- Tri de chaînes = tri temporelL'ordre lexicographique est l'ordre temporel : trier des ULID comme de simples chaînes les trie par heure de création sans analyse — utile dans les lignes de journaux, noms de fichiers et magasins clé-valeur.
- 26 caractères sûrsCompact et sûr pour URL : 26 caractères insensibles à la casse, sans tirets ni symboles, plus court que les 36 d'un UUID et sûr dans tout segment de chemin ou paramètre de requête.
- Monotone à la millisecondeDans une même milliseconde, l'ordre vient de la partie aléatoire ; les générateurs qui l'incrémentent de façon monotone — comme le générateur de lots Toolars — gardent même les identifiants de même milliseconde dans l'ordre de génération.
Les ID aléatoires fragmentent vos index
Un index B-tree est ordonné, et insérer un UUID v4 aléatoire écrit dans une feuille aléatoire à chaque fois : les pages se scindent, le cache tampon tourne, et l'index gonfle d'espace mort. Les identifiants ordonnés dans le temps s'ajoutent près du bord droit de l'index, transformant les insertions en meilleur cas du B-tree.
Voilà pourquoi le choix se fait à la conception du schéma, pas après le premier trimestre lent : migrer une clé primaire signifie réécrire chaque ligne et chaque clé étrangère qui y fait référence. Si la table reste petite, le désordre de v4 ne devient jamais visible ; si elle grandit vers des centaines de millions de lignes sous écriture constante, les formats ordonnés paient leur loyer dès le premier jour.
- L'aléatoire disperseAvec v4 comme clé primaire, les tables à fortes insertions montrent plus de scissions de pages, des facteurs de remplissage plus faibles et un débit d'écriture mesurablement pire qu'avec une clé ordonnée de même taille.
- L'ordonné ajoutev7 et ULID améliorent la localité de l'index sans coordination centrale. Des ID voisins dans un lot monotone peuvent être prévisibles : appliquez toujours des contrôles d'autorisation indépendants de l'identifiant.
- Mesurer le compromisLe compromis est réel mais modeste : 128 bits, c'est le double du stockage d'un bigint, et les clés ordonnées concentrent les écritures du jour sur le bord droit de l'index, ce qui ne compte qu'à de très hauts débits d'insertion.
Collisions, URL et ce qu'un ID révèle
Avec 122 bits aléatoires indépendants en v4, un milliard d'identifiants donne une probabilité de collision d'environ un sur 10^19. Les 80 bits aléatoires d'ULID protègent un autre budget : les identifiants créés dans la même milliseconde.
Collez toute valeur suspecte dans le validateur : il reconnaît la forme canonique d'UUID à 36 caractères avec sa variante RFC 9562 et son quartet de version, l'alphabet ULID de 26 caractères avec sa règle de dépassement, et il rapporte l'horodatage embarqué pour les formats ordonnés dans le temps — une valeur tirée d'un journal vous dit ce qu'elle est avant que vous ne construisiez dessus.
- Probabilité négligeableAucun des deux formats n'est une frontière de sécurité : un identifiant dans une URL convient pour adresser, mais quiconque le voit peut le citer — l'autorisation doit venir de contrôles d'accès, pas de l'opacité de l'ID.
- Les ID ne sont pas des secretsv7 et ULID fuient l'heure de création par conception ; le validateur l'extrait ouvertement. C'est généralement une métadonnée inoffensive, mais décidez-le consciemment pour les objets exposés au public.
- Le temps est visibleLes ID de base de données séquentiels fuient le volume et le rythme de croissance ; les identifiants aléatoires et temporo-aléatoires ne révèlent rien du nombre d'enregistrements existants.
Générez et validez sans serveur
La génération d'identifiants n'a besoin que d'une seule ressource rare — du bon aléa — et le navigateur l'a déjà. L'espace de travail puise dans crypto.getRandomValues, génère des lots entièrement dans l'onglet et ne transmet jamais de valeur.
- 1 à 100 par lotChoisissez UUID v4, UUID v7 ou ULID et générez de 1 à 100 par lot ; les lots v7 et ULID incrémentent le champ aléatoire de façon monotone, donc tout un lot reste dans l'ordre de génération.
- Casse et exportLa casse de sortie est un choix d'affichage : canonique, majuscules ou minuscules, avec copie globale plus des téléchargements en texte délimité par des sauts de ligne et en CSV qui enregistrent l'heure embarquée de chaque identifiant.
- Validation instantanéeLa validation répond instantanément aux questions de structure : longueur, alphabet, version et variante d'UUID, valeurs spéciales nil et max, dépassement ULID, et l'horodatage embarqué en UTC.
ULID est du base32 ; vos jetons sont probablement du Base64.
Les encodages d'octets en texte se cachent sous chaque identifiant et chaque jeton — apprenez ce qu'ils coûtent et où ils gagnent leur place.