Comparison
UUID v4 vs v7: usa v7 para claves de base de datos
v4 para tokens opacos. v7 para todo lo demás, especialmente claves de base de datos.
By Buğra SözeriPublished
Resumen. UUID v4 tiene 122 bits de aleatoriedad pura y no es ordenable, lo cual destruye el rendimiento del índice B-tree cuando se usa como clave de base de datos. UUID v7 (RFC 9562, 2024) antepone una marca de tiempo Unix de 48 bits en milisegundos para que los IDs se ordenen por tiempo de creación. Usa v7 para claves de base de datos e IDs de eventos; mantén v4 para tokens de sesión opacos.
Los UUIDs son identificadores de 128 bits diseñados para ser globalmente únicos entre sistemas sin coordinación. La especificación original (RFC 4122, 2005) definió cinco versiones; v4 (puramente aleatorio) fue la única que la mayoría de los desarrolladores usaba. RFC 9562 (2024) añadió v7, y v7 debería ser el nuevo valor predeterminado para casi todos los casos de uso donde anteriormente se elegía v4.
Las diferencias principales
| Propiedad | v4 | v7 |
|---|---|---|
| Especificado | RFC 4122 (2005) | RFC 9562 (2024) |
| Bits aleatorios | 122 | 74 |
| Marca de tiempo incrustada | No | Sí (48 bits ms desde época) |
| Ordenable por tiempo de creación | No (puramente aleatorio) | Sí (lexicográfico = cronológico) |
| Probabilidad de colisión | ~1 en 10³⁶ para cualquier par | Efectivamente cero (marca de tiempo + aleatorio combinados) |
| Compatibilidad con índice de base de datos | Mala (inserción aleatoria agita B-trees) | Excelente (secuencial, favorable al añadir) |
| Soporte en navegador | crypto.randomUUID() desde 2021 | Generación manual (sin API nativa aún) |
Por qué v4 perjudica las bases de datos
Las claves primarias de bases de datos típicamente viven en un índice B-tree. Los B-trees funcionan mejor cuando las inserciones llegan en orden ordenado: las nuevas claves se añaden al extremo derecho de la hoja, sin necesidad de reequilibrio, la página del índice permanece caliente en la caché.
Las claves aleatorias (v4) destruyen todo eso. Cada inserción cae en una página aleatoria, potencialmente causando una división de página, causando con certeza fallos de caché, y produciendo espacio libre disperso por el índice que nunca se compacta. Para cargas de trabajo con muchas escrituras esto se manifiesta como:
- 10-100× más E/S que las claves secuenciales a la misma velocidad de escritura
- Archivos de índice inflados (a menudo 2-3× el tamaño que tendrían con claves ordenadas)
- Ralentizaciones de consultas a medida que la tasa de aciertos de caché se degrada
Los benchmarks de Postgres vs MySQL comparando UUID v4 con claves primarias bigint consistentemente muestran una diferencia de rendimiento de escritura de 2-5× en cargas de trabajo representativas. La solución no es abandonar los UUIDs — es usar el tipo de UUID que se ordena.
Cómo se ve v7
Un UUID v7:
01950d29-4f6f-7234-bf01-a8b3c0d9e102 └─────timestamp_ms──────┘ └──random──┘
Primeros 48 bits: marca de tiempo Unix en milisegundos (válido hasta ~10889 d.C.). Siguientes 4 bits: versión (siempre 7). Siguientes 12 bits: aleatorio. Luego 2 bits de marcador de variante + 62 bits de aleatorio. Total aleatorio: 74 bits — cómodamente resistente a colisiones.
Dos UUIDs v7 creados en el mismo milisegundo compiten en los 74 bits de aleatorio; la probabilidad de colisión dentro de ese milisegundo es aproximadamente 10⁻²² para un sistema de mil millones de IDs. Entre milisegundos, la marca de tiempo hace que las colisiones sean estructuralmente imposibles.
Cuándo v4 sigue siendo la elección correcta
- Tokens de sesión opacos donde no quieres filtrar el orden de creación. v7 filtra marcas de tiempo de creación con resolución de ~milisegundo en el prefijo, lo cual está bien para claves de base de datos pero es malo para tokens sensibles a la privacidad.
- Claves de API, tokens de acceso, tokens de restablecimiento de contraseña: la opacidad importa más que la ordenabilidad.
- Identificadores de anonimización: donde observar la marca de tiempo ayudaría a un atacante a correlacionar.
Cuándo v7 es claramente mejor
- Claves primarias de base de datos.
- IDs de sistemas distribuidos (IDs de evento, IDs de pedido, IDs de traza).
- Cualquier lugar donde te beneficiarías de poder usar ORDER BY id y obtener ordenación cronológica de forma gratuita.
- Cualquier lugar donde las consultas de rango por tiempo de creación de otro modo necesitarían un índice separado en created_at.
La ruta de migración
Nuevas tablas: usa v7 desde el principio. Tablas antiguas: normalmente no vale la pena migrar, pero si estás alcanzando topes de rendimiento de escritura en una tabla con clave UUID, cambiar a v7 es un cambio estructural que vale la pena.
Genera cualquiera de los dos con nuestro generador de UUID, que admite ambas versiones.
Datos numéricos
- Longitud de cadena: ambos son 36 caracteres con guiones (32 hex + 4 guiones), 32 chars sin guiones, 22 chars en base64url, 16 bytes en bruto.
- Entropía: v4 tiene 122 bits aleatorios (6 bits consumidos por marcadores de versión + variante); v7 tiene 74 bits aleatorios después de la marca de tiempo de 48 bits.
- Matemáticas de colisión v4: probabilidad de colisión del 50% después de generar ~2⁶¹ ≈ 2,3 × 10¹⁸ UUIDs — genera mil millones por segundo y esperarías ~85 años.
- Rango de marca de tiempo v7: campo Unix-milisegundo de 48 bits cubre año 1970 a año 10889.
- Benchmark B-tree de Postgres (Percona, 2023): ~7.000 inserciones/seg con v4 frente a ~28.000 inserciones/seg con v7/ULID en el mismo hardware y esquema — una diferencia de 4× que se amplía a medida que el índice crece más allá de la RAM.
- Inflado del índice: una tabla con 100 M de filas con clave v4 comúnmente termina siendo 2-3× más grande en disco que los mismos datos con clave v7 o un bigint secuencial, debido al espacio libre dejado tras las divisiones de página.
- Velocidad de generación:
crypto.randomUUID()(v4) corre a ~3 M ops/seg en Node 20; las implementaciones v7 (uuid v9, ulid) marcan ~2,5 M ops/seg.
Matriz de decisión
| Caso de uso | Elige |
|---|---|
| Clave primaria Postgres / MySQL | v7 (o ULID) |
| ID de evento distribuido, ID de traza, ID de pedido | v7 |
| Token de sesión, token CSRF | v4 (la opacidad importa) |
| Token de restablecimiento de contraseña / magic-link | v4 + TTL corto |
| Prefijo de clave de API | v4 |
| Clave de objeto S3 (listado ordenable) | v7 |
| Clave de idempotencia en entrega de webhook | v7 (orden cronológico favorable para depuración) |
| Slug público | Ninguno — usa NanoID o hash corto |
Fuentes
- RFC 9562 — Universally Unique IDentifiers (UUIDs), mayo 2024 — rfc-editor.org/rfc/rfc9562 (define v6, v7, v8; reemplaza RFC 4122).
- Percona Blog — UUIDs in Databases: A Deep Dive, benchmarks v4 vs claves secuenciales — percona.com.
Frequently asked questions
- ¿Es UUID v7 retrocompatible con v4?
- Sí — ambos son identificadores de 128 bits en el mismo formato hex 8-4-4-4-12, ambos caben en cualquier columna o API que acepte un UUID v4, y ambos codifican su versión en el mismo nibble. La migración es puramente sobre cómo generas nuevos IDs; los v4 existentes en la base de datos siguen funcionando sin cambios.
- ¿Filtra v7 la marca de tiempo de creación?
- Sí — los primeros 48 bits son la marca de tiempo Unix en milisegundos, legible por cualquiera que vea el UUID. Para la mayoría de las claves de base de datos esto está bien o incluso es útil, pero para tokens de sesión opacos o códigos de restablecimiento de contraseña donde no quieres exponer el orden de creación, mantén v4.
- ¿Por qué v4 perjudica el rendimiento de las bases de datos?
- Porque las claves aleatorias aterrizan en páginas aleatorias de un índice B-tree en cada inserción, causando divisiones de página y destruyendo la localidad de caché. Las claves secuenciales (como el prefijo de marca de tiempo de v7) se añaden al extremo derecho de la hoja y permanecen favorables para la caché. Los benchmarks de Postgres y MySQL típicamente muestran una diferencia de rendimiento de escritura de 2-5×.
- ¿Puedo generar UUIDs v7 en el navegador?
- No de forma nativa aún — crypto.randomUUID() devuelve v4. Necesitas una pequeña librería (uuid v9+, polyfills basados en ulid) o 10 líneas de código combinando Date.now() con crypto.getRandomValues(). El soporte nativo de v7 está en el plan de trabajo de WHATWG.
Related
Published May 15, 2026