UUID v4 vs. v7: ¿cuál deberías usar?
UUID v4 vs v7 para claves primarias de base de datos: por qué v7 mejora las inserciones, cuándo v4 protege la privacidad y cómo generar ambos.
Para una nueva clave primaria de base de datos en 2026, opta por defecto por UUID v7 y recurre a v4 solo cuando el identificador sea público y su hora de creación deba permanecer privada.
Si alguna vez has visto cómo la latencia de inserción se disparaba en una tabla con mucho tráfico y has rastreado el problema hasta una clave primaria que aterriza en un rincón distinto del índice cada vez, esta pregunta te resultará familiar. Resulta que la solución es mucho más sencilla que una migración de esquema. Ambos formatos son UUID de 128 bits estandarizados en el mismo RFC, así que la elección no tiene que ver con la compatibilidad ni con la seguridad frente a colisiones. Se reduce a una sola propiedad: si tus IDs se ordenan o no según el orden de creación. La ordenación temporal de v7 corrige la fragmentación de índices que provocan las claves aleatorias v4 en tablas con mucha escritura, a costa de incrustar una marca de tiempo legible en cada valor. Esta guía desglosa la diferencia estructural, el mecanismo de indexación de la base de datos que hay detrás del rendimiento de escritura de v7, el compromiso en materia de privacidad, el soporte actual de las bibliotecas y una recomendación por defecto contundente.
Puntos clave
- UUID v4 y v7 son identificadores de 128 bits y 16 bytes estandarizados en el RFC 9562 (mayo de 2024); v7 sustituye los 48 bits iniciales por una marca de tiempo Unix en milisegundos, de modo que sus valores se ordenan según el orden de creación, mientras que v4 es totalmente aleatorio.
- Las claves aleatorias v4 se dispersan por un índice B-tree y provocan divisiones de página, rotación de caché y fragmentación; el prefijo ordenado temporalmente de v7 hace que las inserciones se añadan cerca del final del índice, comportándose de forma mucho más parecida a una clave secuencial.
- Un ID v7 revela su propia hora de creación con precisión de milisegundos; un ID v4 no. Usa v4 para identificadores públicos, enlaces de invitación o cualquier caso en el que tu tasa de crecimiento deba permanecer privada.
- El soporte de v7 es de primer nivel: PostgreSQL 18 incluye
uuidv7()de forma nativa, Python 3.14 añadióuuid.uuid7()y el paquete de JavaScriptuuid(v14.x) exportav7(). - Ningún UUID es un secreto: usa un token aleatorio dedicado de 256 bits para la autenticación y reserva los UUID para la identidad.
¿Cuál es la diferencia entre UUID v4 y v7?
UUID v4 y v7 son identificadores de 128 bits y 16 bytes estandarizados en el RFC 9562, publicado en mayo de 2024 como documento en vía de estándar (Standards Track) que deja obsoleto al antiguo RFC 4122. La única diferencia estructural está en el origen de los bits. UUID v4 consta de 122 bits de aleatoriedad, con 6 bits reservados para los marcadores de versión y variante, lo que lo hace completamente aleatorio y sin orden. UUID v7 sustituye los 48 bits iniciales por una marca de tiempo Unix en milisegundos y rellena los ~74 bits restantes con aleatoriedad (más los marcadores de versión y variante), de modo que los valores v7 se ordenan según el orden de creación, tanto léxica como byte a byte, mientras que los valores v4 no.
UUID v4: [ 122 random bits ...................... ] + version/variant
UUID v7: [ 48-bit ms timestamp ][ ~74 random bits ] + version/variant
Ese único cambio constituye toda la decisión. Ambos mantienen la misma matemática de colisiones derivada de la porción aleatoria, ambos caben en la misma columna y ambos están cubiertos por el mismo estándar.
Discover how at OpenReplay.com.
¿Por qué UUID v7 gana como clave de base de datos?
v7 supera a v4 como clave primaria porque su prefijo de marca de tiempo aporta a las inserciones una localidad de índice que las claves aleatorias destruyen. Las claves aleatorias v4 aterrizan en posiciones arbitrarias de un índice B-tree, provocando divisiones de página, rotación de caché y fragmentación, ya que cada inserción apunta a una parte distinta del árbol. Este es exactamente el problema que el RFC 9562 señala como motivo para definir v7: cuando los identificadores no llevan ninguna ordenación temporal, cada nueva fila debe escribirse allí donde caiga su valor aleatorio, mientras que los valores generados uno tras otro bajo un esquema ordenado temporalmente acaban siendo vecinos en el índice. El prefijo monótono de v7 implica que las nuevas filas se añaden cerca del final del índice, por lo que las divisiones de página se vuelven infrecuentes y el rendimiento de inserción se aproxima al de una clave entera secuencial, conservando al mismo tiempo la seguridad frente a colisiones y la generación distribuida propias de los UUID.
La penalización es peor en motores con índice agrupado (clustered index). En MySQL InnoDB y SQL Server, la tabla está ordenada físicamente por la clave primaria, de modo que las inserciones aleatorias reescriben páginas por toda la estructura. PostgreSQL almacena las filas en un heap con índices separados, lo que lo hace menos sensible a la aleatoriedad de las claves, pero sus índices siguen perdiendo localidad de caché con claves v4 aleatorias. La magnitud varía según el motor, la carga de trabajo y el hardware, así que trata con escepticismo los porcentajes concretos de benchmarks de blogs sin fuentes y mide tu propia tabla. El mecanismo en sí no está en discusión.
La ordenación temporal también se mantiene en ráfagas de inserciones. Las implementaciones añaden un contador submilisegundo para que los IDs generados en el mismo milisegundo sigan ordenándose correctamente: uuid.uuid7() de Python reserva 42 bits como contador para que los valores acuñados dentro de un mismo milisegundo mantengan su orden, y uuidv7() de PostgreSQL 18 construye cada valor a partir de una marca de tiempo Unix en milisegundos, una fracción submilisegundo y bits aleatorios.
Cuándo UUID v4 sigue siendo la opción correcta
Elige v4 cuando el ID esté expuesto y su hora de creación sea sensible, porque un ID v7 incrusta su propia hora de creación con precisión de milisegundos. Cualquiera que pueda leer el ID puede saber cuándo se creó el registro, lo que hace que v7 encaje mal como identificador de cara al público. El equipo de Aiven llega a la misma conclusión: en cuanto una clave primaria se entrega a los usuarios finales a través de una aplicación o API externa, v7 deja de ser una elección sensata, porque el identificador revela cuándo se creó el registro. Usa v4 para tokens de invitación, enlaces para compartir o cualquier caso en el que un competidor pudiera inferir tu tasa de crecimiento a partir de los rangos de IDs.
Hay una salvedad que se aplica a ambas versiones: ningún UUID es un token de seguridad. Los bits no aleatorios de v7 son predecibles, y la calidad de la aleatoriedad de v4 depende de la implementación, así que ninguno de los dos debería controlar el acceso en la autenticación. Genera una cadena criptográficamente aleatoria dedicada, de al menos 256 bits, para los secretos, y usa los UUID únicamente para la identidad.
Generar v7 hoy y migrar de forma incremental
El soporte de v7 es ya amplio en bases de datos y lenguajes, aunque la versión exacta importa:
| Plataforma | Generación de v7 | Versión |
|---|---|---|
| PostgreSQL | uuidv7() (nativa) | PostgreSQL 18 |
| Python | uuid.uuid7() (stdlib) | Python 3.14 |
| JavaScript / Node | v7() de uuid | uuid v14.x |
PostgreSQL 18 incorporó uuidv7() como función nativa y añadió un alias uuidv4() para el ya existente gen_random_uuid(); en PostgreSQL 17 y versiones anteriores necesitas una extensión o una biblioteca del lado de la aplicación. Python añadió uuid.uuid7() a la biblioteca estándar en la versión 3.14, no en la 3.12, donde la llamada lanza AttributeError. En JavaScript, el paquete uuid expone v7 mediante una importación con nombre en ESM y, según su changelog, el paquete dejó de dar soporte a CommonJS en la v12:
// Node.js, uuid v14.x
import { v7 as uuidv7 } from "uuid";
const id = uuidv7();
-- PostgreSQL 18
SELECT uuidv7();
Si quieres ver la diferencia antes de comprometerte con un tipo de columna, genera un lote de cada uno y compáralos. El generador de UUID de OpenReplay produce valores v4 o v7 en el navegador, hasta 500 a la vez, con opciones para mayúsculas, sin guiones y salida entrecomillada, de modo que puedas pegarlos directamente en SQL o en un fixture JSON. Ordena una columna de valores v7 y saldrán en orden de creación; haz lo mismo con v4 y se dispersarán. Los valores provienen de la Web Crypto API en tu propia pestaña, así que ninguno de ellos se envía a ninguna parte.
La migración no requiere reescritura. v4 y v7 comparten el mismo tipo de columna uuid de 16 bytes, de modo que puedes conservar las filas v4 existentes y generar las nuevas filas como v7 en la misma tabla. La versión está codificada en el valor y no se necesita ningún backfill. Las nuevas inserciones se agrupan al final del índice y la fragmentación se alivia gradualmente a medida que las páginas se reescriben con el tiempo; se trata de un efecto progresivo, no de una desfragmentación instantánea.
El veredicto: ¿cuál deberías usar?
Opta por defecto por UUID v7 para nuevas claves primarias de bases de datos, logs y flujos de eventos; elige v4 cuando la imprevisibilidad sea importante. v7 te ofrece el rendimiento de escritura de una clave secuencial junto con la seguridad frente a colisiones y la generación distribuida de un UUID, y ahora cuenta con soporte nativo en las plataformas que la mayoría de los equipos ya utilizan. Reserva v4 para identificadores que sean públicos y en los que la hora de creación deba permanecer privada.
Dos alternativas completan el panorama de la decisión. ULID codifica la misma idea de marca de tiempo más aleatoriedad en base32 de Crockford, ofreciendo una cadena más corta de 26 caracteres apta para URLs, pero no es un estándar del IETF y carece de un tipo de columna uuid nativo. El clásico bigint autoincremental sigue siendo la opción más compacta y rápida para un sistema pequeño de un solo nodo que nunca vaya a necesitar generación distribuida de IDs.
Si hoy estás levantando una nueva tabla y sufres problemas de índice por culpa de las claves v4, cambia las nuevas inserciones a v7, deja tus filas antiguas donde están y deja que el índice se estabilice. La mejora está a tu alcance prácticamente sin coste de migración.
Preguntas frecuentes
¿Se puede extraer la marca de tiempo de creación de un valor UUID v7?
Sí. Como UUID v7 almacena una marca de tiempo Unix de 48 bits en milisegundos en sus bits iniciales, puedes decodificar cuándo se generó el valor. PostgreSQL 18 expone uuid_extract_timestamp() precisamente para esto, y se amplió para dar soporte a valores de la versión 7. Esto es una ventaja para depuración y consultas por rangos temporales, pero también es la razón por la que v7 revela la hora de creación y no debería usarse para identificadores públicos cuando esa información temporal sea sensible.
¿Tienen UUID v7 y v4 el mismo riesgo de colisión?
No, pero la diferencia es insignificante en la práctica. UUID v4 aporta 122 bits aleatorios, mientras que v7 conserva alrededor de 74 bits aleatorios tras reservar 48 bits para la marca de tiempo más los marcadores de versión y variante. v7 tiene menos bits aleatorios, pero las colisiones solo son posibles entre IDs generados en el mismo milisegundo, y las implementaciones añaden un contador monótono dentro de esa ventana. Para cargas de trabajo reales, ambos están efectivamente libres de colisiones a cualquier tasa de generación realista.
¿Mejora UUID v7 el rendimiento de las consultas de lectura o solo el de las inserciones?
v7 ayuda principalmente al rendimiento del lado de la escritura y a los escaneos por rangos, al ordenar las filas próximas entre sí en el índice, lo que reduce las divisiones de página y mejora la localidad de caché. No atribuyas a v7 por sí solo grandes mejoras de lectura. La mejora oficial de lectura de 'hasta 3x' de PostgreSQL 18 proviene de su nuevo subsistema de E/S asíncrona, una funcionalidad independiente de uuidv7(). El alcance real del beneficio de rendimiento de v7 es la localidad de índice y el rendimiento de inserción.
¿Debería migrar mis claves primarias UUID v4 existentes a v7?
Normalmente no es necesaria una migración completa. v4 y v7 comparten el mismo tipo de columna uuid de 16 bytes y la versión está codificada en el valor, así que puedes dejar intactas las filas v4 existentes y generar las nuevas filas como v7 en la misma tabla sin ningún backfill. Las nuevas inserciones se agrupan al final del índice y la fragmentación se alivia gradualmente a medida que se reescriben las páginas. Reescribir las filas antiguas solo merece la pena si la fragmentación ya está causando problemas medibles.