Un UUID est un identifiant de 128 bits pensé pour être généré sans coordination centrale. UUID, c'est quoi au juste ? C'est une brique discrète, mais très utile dès qu'une application web doit créer des références robustes entre API, base de données, files de messages ou services distribués. Je vais aller droit au but: définition claire, structure, versions à connaître, bons usages et pièges à éviter.
Ce qu’il faut retenir en une minute
- Un UUID fait 128 bits et s’écrit le plus souvent en 36 caractères hexadécimaux au format 8-4-4-4-12.
- Le standard actuel est RFC 9562, qui a remplacé RFC 4122 et introduit les versions 6, 7 et 8.
- UUIDv4 reste le choix simple pour un identifiant aléatoire; UUIDv7 est souvent plus adapté aux bases et aux clés triables.
- Un UUID identifie une ressource, mais ne protège pas cette ressource à lui seul.
- En base, je privilégie le stockage binaire quand c’est possible; le texte est plus lisible, mais plus lourd.
Ce qu’est un UUID et pourquoi il existe
Un UUID, pour Universally Unique Identifier, est un identifiant conçu pour rester unique sans demander à un serveur central de distribuer des numéros. Dans les environnements modernes, c’est précieux: plusieurs services peuvent créer des objets en parallèle, des clients peuvent travailler hors ligne, et des bases différentes peuvent fusionner leurs données sans devoir réattribuer des clés.
Le point important, c’est qu’un UUID n’est pas un simple “gros nombre au hasard”. C’est un format standardisé, compatible avec des usages très différents: clés primaires, identifiants publics dans une URL, IDs d’événements, références de documents, ou corrélation de traces. Le standard actuel, RFC 9562, a remplacé RFC 4122 et clarifie justement ces usages pour les projets actuels.
Je fais aussi une distinction utile: un UUID n’est pas un secret, ni une autorisation. Il sert à reconnaître un objet, pas à prouver qu’un utilisateur a le droit d’y accéder. Pour une API, cette nuance évite beaucoup d’erreurs de design. Pour comprendre pourquoi, il faut maintenant regarder sa forme concrète.

Comment lire sa structure sans se perdre
À l’écran, un UUID apparaît souvent sous cette forme: 8-4-4-4-12 caractères hexadécimaux séparés par des tirets. Au total, cela fait 36 caractères, pour représenter 16 octets, donc 128 bits. Les lettres peuvent être en minuscules ou en majuscules; le sens ne change pas.
| Partie | Taille | Rôle |
|---|---|---|
| Premier bloc | 8 hexadécimaux | Une portion du champ principal de l’identifiant |
| Deuxième bloc | 4 hexadécimaux | Une autre portion du champ interne |
| Troisième bloc | 4 hexadécimaux | Contient notamment le numéro de version |
| Quatrième bloc | 4 hexadécimaux | Contient le variant, qui indique la structure interne |
| Cinquième bloc | 12 hexadécimaux | Le reste des bits de l’identifiant |
Deux valeurs spéciales méritent d’être connues. Le nil UUID est l’identifiant tout à zéro, utile pour signifier “aucune valeur”. À l’autre extrémité, le max UUID est l’identifiant tout à un, parfois utilisé comme borne technique. En pratique, on les voit peu dans les applications métier, mais ils existent dans le standard.
Le détail qui compte pour les développeurs est ailleurs: la version influence la façon dont l’UUID est produit, et donc son comportement en base, en tri et en débit. C’est ce point qui fait vraiment la différence entre les variantes.
Les versions à connaître en 2026
Toutes les versions ne se valent pas pour un projet web actuel. Certaines sont historiques, d’autres restent utiles, et deux ou trois seulement comptent vraiment quand on démarre une architecture neuve. Je résume les plus importantes dans le tableau ci-dessous.
| Version | Principe | Atout principal | Limite ou usage |
|---|---|---|---|
| v1 | Timestamp + identifiant de nœud | Tri temporel approximatif | Peut exposer des informations sur la machine; je l’évite en contexte sensible |
| v3 | Nom + MD5 dans un namespace | Déterministe: même entrée, même sortie | Plutôt legacy; utile seulement si vous assumez MD5 et la logique par nom |
| v4 | Aléatoire | Simple, universel, très répandu | Pas ordonné; peut fragmenter davantage certains index |
| v5 | Nom + SHA-1 dans un namespace | Déterministe, plus cohérent que v3 | Encore basé sur SHA-1; réservé aux cas où le déterminisme est utile |
| v6 | Version temporelle réordonnée | Meilleur tri que v1 | Intéressante surtout pour migration ou compatibilité |
| v7 | Timestamp Unix en millisecondes + aléa | Très bon compromis pour les bases et l’ordre d’insertion | Mon choix de référence pour un nouveau projet quand la stack le supporte |
| v8 | Zone personnalisable | Flexibilité maximale | À réserver à des besoins précis; la compatibilité dépend de votre implémentation |
Si je devais simplifier brutalement: v4 pour la simplicité et l’aléa, v7 pour les projets récents qui veulent garder un bon comportement de tri, et v3/v5 seulement quand j’ai besoin d’un UUID déterministe à partir d’un nom. Le standard actuel recommande d’ailleurs d’utiliser UUIDv7 plutôt que v1 ou v6 quand c’est possible.
Autrement dit, la bonne version dépend moins de la mode que de votre architecture. Et c’est exactement ce qui amène à la comparaison avec l’auto-incrément classique.
Quand je le choisis plutôt qu’un identifiant auto-incrémenté
Le débat n’est pas théorique. Dans un monolithe simple avec une seule base, un identifiant auto-incrémenté reste souvent très confortable. Il est compact, lisible, et les index sont généralement plus petits. Mais dès qu’on passe à des services distribués, à de la réplication, à des écritures concurrentes ou à de la synchronisation entre plusieurs environnements, l’UUID devient beaucoup plus solide.
| Critère | UUID | Auto-incrément |
|---|---|---|
| Génération distribuée | Excellente | Faible si plusieurs nœuds écrivent en parallèle |
| Lisibilité humaine | Faible | Bonne |
| Taille de stockage | Plus élevée, surtout en texte | Plus faible |
| Prévisibilité | Faible, donc plus difficile à deviner | Élevée, donc facile à énumérer |
| Fusion de systèmes | Très pratique | Souvent pénible |
| Comportement d’index | Variable selon la version; v7 aide beaucoup | Souvent favorable |
Je retiens une règle simple: si vos données peuvent être créées loin de la base centrale, ou si vous exposez l’identifiant publiquement, l’UUID mérite une vraie place dans le design. Si tout vit dans un seul système, avec un volume raisonnable et peu d’exposition externe, l’auto-incrément reste défendable. Le vrai gain de l’UUID, ce n’est pas le prestige technique, c’est la liberté d’architecture.
Mais cette liberté a un prix, et c’est là que beaucoup d’équipes se trompent au moment de l’implémentation.
Les erreurs qui coûtent cher dans un projet réel
Je vois souvent les mêmes faux pas revenir. Ils ne cassent pas forcément le projet tout de suite, mais ils créent des coûts cachés: performances moins stables, sécurité mal comprise, migration plus difficile, ou dette technique inutile.
- Croire qu’un UUID est un secret alors qu’il ne remplace jamais une vraie autorisation.
- Stocker systématiquement en texte sans vérifier si la base propose un type natif ou un stockage binaire plus compact.
- Utiliser v1 dans un contexte sensible alors que la présence d’un identifiant de machine et du temps peut poser un problème de confidentialité.
- Choisir un UUID déterministe sur un nom mutable, puis découvrir que le nom métier change et casse le modèle de données.
- Ignorer l’ordre des insertions dans une base volumineuse alors que la version choisie influence l’indexation et la fragmentation.
- Générer côté client sans vérifier la qualité de l’aléa, surtout si la bibliothèque ou l’environnement n’est pas fiable.
Le point de sécurité le plus important est simple: un UUID est difficile à deviner, mais ce n’est pas une barrière d’accès. Si une route API reste accessible uniquement parce qu’elle contient un UUID, le problème n’est pas l’UUID, c’est la logique d’accès. De la même manière, un UUID ne doit jamais servir de mot de passe déguisé.
Pour réduire les risques techniques, je recommande aussi de faire attention au format de stockage. En base, un identifiant binaire ou un type natif économise de la place; en texte, vous gagnez en portabilité, mais vous payez en taille et parfois en index. Une fois ces pièges identifiés, il devient plus facile de l’utiliser proprement dans une vraie API.
Comment je l’emploie dans une API, une base et des logs
Dans une API REST, j’aime bien exposer un UUID dans l’URL publique d’une ressource quand je veux éviter la prédictibilité des IDs séquentiels. Par exemple, `/users/7f3a...` est moins exposé à l’énumération qu’un `/users/1248`. Cela dit, la protection réelle vient toujours de l’authentification et des droits, pas du format de l’identifiant.
Dans une base SQL ou NoSQL, je choisis le format selon le moteur. Si la base gère un type UUID natif, je l’utilise. Sinon, je préfère souvent un stockage binaire de 16 octets plutôt qu’une chaîne de 36 caractères, surtout quand le volume monte. Pour les schémas orientés écriture intensive, UUIDv7 est souvent plus agréable parce qu’il conserve une logique temporelle utile au tri et à l’indexation.
Dans les logs, les files de messages et les systèmes d’observabilité, l’UUID est aussi très utile comme identifiant de corrélation. Je peux suivre la trace d’une requête à travers plusieurs services sans exposer de logique métier sensible. Là encore, je garde une règle stricte: corrélation oui, autorisation non.
- Pour un identifiant public stable, j’utilise un UUID lisible et homogène dans toute la stack.
- Pour des écritures distribuées, je préfère un générateur local avec une version adaptée, souvent v7.
- Pour des intégrations entre services, je standardise le format d’échange dès le départ.
- Pour les gros volumes, je vérifie le coût d’indexation avant de valider le choix final.
Avec ces repères, l’usage devient plus propre et plus prévisible. Il reste une question pratique: quel choix faire quand on démarre un projet neuf?
Le réflexe que je recommande pour un projet neuf
En 2026, sur un nouveau projet backend ou web, mon réflexe est assez net: UUIDv7 si la bibliothèque et la base le supportent correctement, sinon UUIDv4 pour rester simple et robuste. Si j’ai besoin d’un identifiant déterministe à partir d’un nom stable, je regarde v5, mais seulement après avoir vérifié que le “nom” en question ne bougera pas dans le temps.
Je résume ma méthode de décision ainsi: je commence par la contrainte d’architecture, pas par la préférence personnelle. Si l’identifiant doit être triable, distribuable et généré à grande vitesse, v7 prend l’avantage. Si l’objectif est juste d’avoir un identifiant solide et largement compatible, v4 reste une valeur sûre. Si je dois construire un système plus spécifique, v8 peut servir, mais seulement avec une gouvernance claire, parce que la liberté de v8 demande plus de discipline.
Au fond, un UUID n’est pas seulement une chaîne de caractères technique. C’est un choix d’architecture qui influence la manière dont vous stockez, triez, exposez et faites circuler vos données. Quand on le choisit avec méthode, il simplifie vraiment la vie du backend, de la base et des services qui gravitent autour.