Ingénierie · 28 août 2026

UUID v4 vs v7 — lequel choisir en 2026

UUID v7 est la nouvelle norme pour les clés primaires de bases de données, mais v4 reste le bon choix pour les tokens de sécurité. Comment choisir, avec comparaison côte à côte et benchmarks.

Pendant 15 ans, le UUID v4 était la seule réponse. Des identifiants aléatoires de 128 bits, générés dans votre navigateur, copiés-collés dans une colonne de base de données, utilisés partout. Ça fonctionnait. Puis en 2024, la RFC 9562 a standardisé v7, et la conversation a changé.

La version courte : utilisez v7 pour les nouvelles clés primaires de base de données, utilisez v4 pour les tokens de sécurité et les IDs de session. Voici pourquoi.

Ce qu’est réellement un UUID

Un UUID est un identifiant de 128 bits, généralement écrit sous forme de 32 caractères hexadécimaux séparés par des tirets : 550e8400-e29b-41d4-a716-446655440000. Les tirets sont cosmétiques ; ce sont les octets qui comptent. Les 128 bits vous donnent 2¹²⁸ valeurs possibles — environ 340 undécillions. Vous n’allez pas en manquer.

Le numéro de version (le premier chiffre après le second tiret — 4 dans 550e8400-e29b-**4**1d4-a716-446655440000) vous indique comment le UUID a été généré. C’est la partie qui compte.

UUID v4 : purement aléatoire

Le UUID v4 est ce que la plupart des gens veulent dire quand ils disent « UUID ». 122 des 128 bits sont aléatoires, les 6 autres encodent la version et la variante. L’aléatoire est tout l’intérêt — il n’y a pas de pattern à exploiter, pas de moyen de deviner le prochain ID, pas de corrélation temporelle.

Générez-en un dans n’importe quel navigateur moderne :

crypto.randomUUID() // → "550e8400-e29b-41d4-a716-446655440000"

C’est magnifiquement simple. C’est aussi, comme il s’avère, terrible pour les bases de données.

Le problème est l’indexation B-tree. Un B-tree est la structure de données derrière la plupart des index (Postgres, MySQL, SQLite, MongoDB). Il garde les données triées pour que les requêtes de plage soient rapides et que les insertions aillent à peu près au même endroit sur le disque. Quand vous insérez un UUID aléatoire, la base de données doit le mettre quelque part au milieu de l’arbre — chaque insertion devient une I/O aléatoire. Avec des millions de lignes, cela tue le débit en écriture.

La solution historique était « utilisez UUID v4 mais avec un ordre séquentiel » — sauf que v4 est, par définition, aléatoire. Les gens ont tricoté autour (le UUID_TO_BIN(..., 1) de MySQL échange les bits temporels vers l’avant). La RFC 9562 a fait du bidouillage la norme.

UUID v7 : ordonné dans le temps

Le UUID v7 place un timestamp à précision milliseconde dans les bits de poids fort et de l’aléatoire dans les bits de poids faible :

0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|                           unix_ts_ms                          |
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|          unix_ts_ms           |  ver  |       rand_a          |
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|var|                        rand_b                             |
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
|                            rand_b                             |
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

Les 48 premiers bits sont le timestamp Unix en millisecondes. Les 4 bits suivants sont la version (7). Puis 74 bits aléatoires, puis 2 bits de variante, puis 48 bits aléatoires supplémentaires.

Le résultat : les UUID générés dans la même milliseconde sont triés par ordre d’insertion. Les UUID générés plus tard sont triés plus tard. Les insertions vont du côté droit du B-tree, pas au milieu. Le débit en écriture augmente de 2 à 10 fois selon la base de données.

Le benchmark qui compte

PlanetScale a publié un benchmark en 2024 qui a chiffré cela. Avec MySQL 8 sur un index de clé primaire :

Format Inserts/sec Notes
Auto-increment INT 35 000 Le plus rapide, mais fuit de l’information
UUID v7 18 000 Comparable à INT pour la plupart des apps
UUID v4 4 500 Insertions aléatoires = scissions de pages
UUID v1 (avec timestamp) 14 000 Variante temporelle plus ancienne

La différence de 4x entre v4 et v7 est le coût de faire des I/O aléatoires. Pour un service à fort trafic, cela se traduit directement par de l’argent.

Quand utiliser v4

Le UUID v4 est toujours le bon choix lorsque l’ID lui-même est la limite de sécurité :

  • Tokens de session — vous ne voulez pas qu’un ID de session révèle son moment de création. Le UUID v7 est trié par temps, ce qui signifie qu’un attaquant qui connaît un ID peut deviner les IDs voisins. (L’exploitabilité pratique est faible — 74 bits d’aléatoire, c’est encore beaucoup — mais le principe compte.)
  • Tokens de réinitialisation de mot de passe — même raisonnement.
  • Clés API distribuées aux tiers — quand l’ID est censé être imprévisible, l’ordre temporel est une fonctionnalité que vous ne voulez pas.
  • Tout utilisé comme sortie CSPRNG — v4 est ce que crypto.randomUUID() retourne. Si vous utilisez l’ID pour de l’aléatoire cryptographique, v4 est le choix naturel.

Quand utiliser v7

Le UUID v7 est le bon choix par défaut pour :

  • Les clés primaires de base de données — c’est le cas d’utilisation phare. La plupart des nouveaux schémas devraient choisir v7.
  • Les IDs de journal d’événements — triables par temps sans colonne de timestamp séparée.
  • Les IDs de messages de file d’attente — ordre FIFO avec unicité.
  • Les identifiants de systèmes distribués où vous voulez un ordre grossier sans coordonner une séquence.

Comment les générer

Dans le navigateur, v4 est intégré :

crypto.randomUUID() // v4

Pour v7, vous avez besoin d’un petit polyfill — crypto.getRandomValues plus un préfixe timestamp. Le générateur UUID sur DevSpeedTools produit à la fois v4 et v7 dans le navigateur en utilisant directement crypto.getRandomValues, vous pouvez donc coller les IDs directement dans votre schéma sans rien installer.

En Node.js 22+, le crypto.randomUUID() intégré ne retourne toujours que v4. Le paquet npm uuid (v9+) a ajouté v7(). En Python, uuid.uuid7() est arrivé en 3.14 (publié en juin 2025) et est maintenant le choix recommandé dans la documentation de la bibliothèque standard. En Postgres, la fonction gen_random_uuid() retourne toujours v4 — pour obtenir v7, générez côté client et passez-le. MySQL 9 (publié en 2024) a ajouté UUID_V7_BIN() en tant que type de première classe, et MariaDB a suivi en 11.7. Cloudflare D1, PlanetScale et Supabase génèrent tous v7 par défaut pour les nouvelles colonnes de clé primaire en 2026.

Migration de v4 à v7

Si vous avez une table existante avec des clés primaires v4, vous n’avez pas besoin de migrer. Les deux versions coexistent dans la même colonne (le type uuid accepte les deux). L’amélioration de performance concerne les insertions, elle n’est donc importante que si vous ajoutez de nouvelles lignes. La migration la plus simple : commencez à générer v7 pour les nouvelles insertions, laissez les lignes existantes en v4. Elles seront légèrement désordonnées par rapport aux nouvelles lignes v7 (puisque v4 n’a pas de timestamp), mais l’index ira bien.

Pour un nouveau schéma en 2026, v7 est le choix par défaut. Le gain de débit en écriture de 4x est réel, la spec est stable, chaque grand runtime a un générateur v7, et les fournisseurs de bases de données gérées utilisent v7 par défaut pour les nouvelles clés primaires. N’optez pour v4 que lorsque vous avez spécifiquement besoin d’IDs imprévisibles et sans corrélation temporelle.