Ingeniería · 28 de agosto de 2026

UUID v4 vs v7 — cuál elegir en 2026

UUID v7 es el nuevo estándar para claves primarias de bases de datos, pero v4 sigue siendo la elección correcta para tokens de seguridad. Cómo elegir, con comparación lado a lado y benchmarks.

Durante 15 años, UUID v4 fue la única respuesta. Identificadores aleatorios de 128 bits, generados en tu navegador, copiados y pegados en una columna de base de datos, usados en todas partes. Funcionó. Luego en 2024, RFC 9562 estandarizó v7, y la conversación cambió.

La versión corta: usa v7 para nuevas claves primarias de bases de datos, usa v4 para tokens de seguridad e IDs de sesión. A continuación está el por qué.

Qué es realmente un UUID

Un UUID es un identificador de 128 bits, generalmente escrito como 32 caracteres hexadecimales separados por guiones: 550e8400-e29b-41d4-a716-446655440000. Los guiones son cosméticos; los bytes son lo que importa. Los 128 bits te dan 2¹²⁸ valores posibles — aproximadamente 340 undecillones. No te vas a quedar sin ellos.

El número de versión (el primer dígito después del segundo guión — 4 en 550e8400-e29b-**4**1d4-a716-446655440000) te dice cómo se generó el UUID. Esa es la parte que importa.

UUID v4: puro aleatorio

UUID v4 es lo que la mayoría de la gente significa cuando dice “UUID”. 122 de los 128 bits son aleatorios, los otros 6 codifican la versión y la variante. La aleatoriedad es todo el punto — no hay patrón que explotar, no hay forma de adivinar el siguiente ID, no hay correlación temporal.

Genera uno en cualquier navegador moderno:

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

Es bellamente simple. También es, como resulta, terrible para bases de datos.

El problema es el indexado B-tree. Un B-tree es la estructura de datos detrás de la mayoría de los índices (Postgres, MySQL, SQLite, MongoDB). Mantiene los datos ordenados para que las consultas de rango sean rápidas y las inserciones vayan aproximadamente al mismo lugar en el disco. Cuando insertas un UUID aleatorio, la base de datos tiene que ponerlo en algún lugar del medio del árbol — cada inserción se convierte en una E/S aleatoria. Con millones de filas, esto destruye el rendimiento de escritura.

La solución histórica fue “usa UUID v4 pero con ordenamiento secuencial” — excepto que v4 es, por definición, aleatorio. La gente lo resolvió (el UUID_TO_BIN(..., 1) de MySQL intercambia los bits de tiempo al frente). RFC 9562 convirtió el truco en estándar.

UUID v7: ordenado por tiempo

UUID v7 pone una marca de tiempo de precisión milisegundo en los bits altos y aleatoriedad en los bits bajos:

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                             |
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

Los primeros 48 bits son la marca de tiempo Unix en milisegundos. Los siguientes 4 bits son la versión (7). Luego 74 bits aleatorios, luego 2 bits de variante, luego 48 bits más aleatorios.

El resultado: los UUID generados en el mismo milisegundo se ordenan por orden de inserción. Los UUID generados después se ordenan después. Las inserciones van al lado derecho del B-tree, no al medio. El rendimiento de escritura aumenta de 2x a 10x dependiendo de la base de datos.

El benchmark que importa

PlanetScale publicó un benchmark en 2024 que puso números. Con MySQL 8 en un índice de clave primaria:

Formato Inserciones/seg Notas
INT autoincremental 35,000 El más rápido, pero filtra información
UUID v7 18,000 Comparable a INT para la mayoría de las aplicaciones
UUID v4 4,500 Inserciones aleatorias = divisiones de página
UUID v1 (con marca de tiempo) 14,000 Variante temporal más antigua

La diferencia de 4x entre v4 y v7 es el costo de hacer E/S aleatoria. Para un servicio de alto tráfico, eso se traduce directamente en dólares.

Cuándo usar v4

UUID v4 sigue siendo la elección correcta cuando el ID en sí es el límite de seguridad:

  • Tokens de sesión — no quieres que un ID de sesión filtre su tiempo de creación. UUID v7 se ordena por tiempo, lo que significa que un atacante que conoce un ID puede adivinar IDs vecinos. (La explotabilidad práctica es baja — 74 bits de aleatoriedad es todavía mucho — pero el principio importa.)
  • Tokens de restablecimiento de contraseña — la misma razón.
  • Claves API distribuidas a terceros — cuando el ID debe ser inadivinable, el ordenamiento por tiempo es una función que no quieres.
  • Cualquier cosa usada como salida CSPRNG — v4 es lo que crypto.randomUUID() devuelve. Si usas el ID para aleatoriedad criptográfica, v4 es el ajuste natural.

Cuándo usar v7

UUID v7 es el predeterminado correcto para:

  • Claves primarias de bases de datos — este es el caso de uso principal. La mayoría de los nuevos esquemas deben elegir v7.
  • IDs de registro de eventos — ordenables por tiempo sin una columna de marca de tiempo separada.
  • IDs de mensajes en cola de mensajes — orden FIFO con unicidad.
  • Identificadores de sistemas distribuidos donde quieres un ordenamiento sin coordinar una secuencia.

Cómo generarlos

En el navegador, v4 está incorporado:

crypto.randomUUID() // v4

Para v7, necesitas un polyfill pequeño — crypto.getRandomValues más un prefijo de marca de tiempo. El generador UUID de DevSpeedTools produce tanto v4 como v7 en el navegador usando crypto.getRandomValues directamente, para que puedas pegar los IDs directamente en tu esquema sin instalar nada.

En Node.js 22+, el crypto.randomUUID() incorporado todavía solo devuelve v4. El paquete npm uuid (v9+) agregó v7(). En Python, uuid.uuid7() llegó en 3.14 (lanzado en junio de 2025) y ahora es la elección recomendada en la documentación de la biblioteca estándar. En Postgres, la función gen_random_uuid() todavía devuelve v4 — para obtener v7, genera del lado del cliente y pásalo. MySQL 9 (lanzado en 2024) agregó UUID_V7_BIN() como un tipo de primera clase, y MariaDB lo siguió en 11.7. Cloudflare D1, PlanetScale y Supabase todos generan v7 por defecto para nuevas columnas de clave primaria en 2026.

Migración de v4 a v7

Si tienes una tabla existente con claves primarias v4, no tienes que migrar. Las dos versiones coexisten en la misma columna (el tipo uuid acepta ambos). La mejora de rendimiento está en las inserciones, por lo que solo importa si estás agregando nuevas filas. La migración más simple: comienza a generar v7 para nuevas inserciones, deja las filas existentes como v4. Se ordenarán ligeramente fuera de orden con las nuevas filas v7 (ya que v4 no tiene marca de tiempo), pero el índice estará bien.

Para un esquema nuevo en 2026, v7 es el predeterminado. La ganancia de 4x en rendimiento de escritura es real, la especificación es estable, cada lenguaje de ejecución importante tiene un generador v7, y los proveedores de bases de datos gestionadas están predeterminando a v7 para nuevas claves primarias. Recurre a v4 solo cuando necesitas específicamente IDs inadivinables y sin correlación temporal.