Aller au contenu principal
Développement 2 min de lecture samedi 11 avril 2026 à 10:00

Les UUID dans Rails : pourquoi les utiliser ?

UUID vs IDs séquentiels : avantages, inconvénients et mise en œuvre avec UUIDv7 dans Rails 7.1+.

Le problème des IDs séquentiels

Quand on crée une application Rails classique, chaque enregistrement reçoit un identifiant numérique auto-incrémenté : /users/1, /users/2, /users/3… C'est simple, lisible, et ça fonctionne très bien dans la plupart des cas.

Mais cette simplicité a un coût. Avec des IDs séquentiels, on expose involontairement plusieurs informations : le volume approximatif de données dans la table, la possibilité d'énumérer les ressources (vulnérabilité IDOR — Insecure Direct Object Reference), et parfois des informations métier sensibles. Un concurrent pourrait par exemple déduire votre nombre de clients simplement en regardant l'URL.

Un UUID comme 550e8400-e29b-41d4-a716-446655440000 ne révèle rien de tout cela.

Les avantages des UUID

Sécurité et opacité — C'est l'argument principal. Les endpoints exposés dans des URLs ou des webhooks ne permettent plus le scraping séquentiel. Impossible de deviner l'identifiant de la ressource suivante.

Génération côté client — On peut créer l'identifiant avant l'insertion en base. C'est particulièrement utile pour du offline-first, des systèmes distribués, ou du pré-assignement dans des formulaires multi-étapes.

Fusion de bases facilitée — Pas de collision d'IDs entre environnements ou entre tenants. C'est très pertinent dans un contexte SaaS multi-tenant où l'on pourrait avoir besoin de fusionner des données.

Sécurité des APIs — Les identifiants exposés dans les APIs REST ou GraphQL ne donnent aucune prise pour de l'énumération.

UUIDv7 : le meilleur des deux mondes

Le reproche historique fait aux UUID v4, c'est leur caractère aléatoire. Les insertions fragmentent l'index B-tree de la clé primaire, provoquant des page splits et des cache misses sur les tables à fort volume d'écriture.

UUIDv7, supporté nativement depuis Rails 7.1 et PostgreSQL, résout ce problème grâce à un préfixe temporel. Les UUIDs sont désormais triés chronologiquement, ce qui élimine la fragmentation d'index tout en conservant tous les avantages d'opacité.

Les inconvénients à connaître

Taille en stockage — Un UUID occupe 16 octets contre 4 (integer) ou 8 (bigint). Cette différence se multiplie sur chaque foreign key, chaque index, chaque jointure. Sur des tables avec beaucoup de relations, l'empreinte mémoire et disque augmente significativement.

Lisibilité dégradée — En debug, dans les logs, en console Rails… User.find("550e8400-e29b-41d4-a716-446655440000") est nettement moins pratique que User.find(42). Même chose dans les URLs et lors du support.

Jointures plus lentes — Comparer des UUIDs est plus coûteux que comparer des entiers, surtout sur de grosses jointures. En pratique avec PostgreSQL et le type natif uuid, la différence reste souvent acceptable, mais elle existe.

Migration complexe — Si vous souhaitez migrer une application existante d'integer à UUID, c'est une opération lourde : toutes les foreign keys à mettre à jour, les associations polymorphiques à revoir, les dépendances externes à adapter.

Mise en œuvre dans Rails

Avec PostgreSQL, l'activation est simple. Dans la configuration des générateurs :

config.generators do |g|
  g.orm :active_record, primary_key_type: :uuid
end

Dans une migration :

create_table :users, id: :uuid do |t|
  t.string :name
  t.timestamps
end

Pour activer UUIDv7 nativement depuis Rails 7.1 :

# config/initializers/generators.rb
Rails.application.config.active_record.generate_uuids_version = 7

Verdict

Pour un nouveau projet, UUIDv7 + PostgreSQL est aujourd'hui un choix solide et quasi sans compromis. On conserve le tri chronologique, on élimine les problèmes de fragmentation d'index, et on gagne tous les avantages de sécurité. Le surcoût en stockage est rarement un facteur bloquant sur des applications métier.

En revanche, migrer un existant uniquement pour passer aux UUID mérite une réflexion au cas par cas : le gain doit justifier la complexité de la migration.

Articles similaires