uuidulidbases de datosidentificadores

UUID v7 y ULID: identificadores únicos que además ordenan por fecha

Por qué el UUID v4 aleatorio castiga tus índices de base de datos y cómo UUIDv7 y ULID resuelven el problema con IDs ordenables y únicos a la vez.

24 de agosto de 2026·7 min de lectura

El UUID v4 aleatorio ha sido la elección por defecto durante quince años, y en bases de datos modernas resulta ser una decisión costosa: sus identificadores llegan en orden completamente aleatorio, lo que fragmenta índices B-tree y destroza el caché de páginas. UUIDv7 —estandarizado oficialmente en RFC 9562 (2024)— y ULID atacan ese problema desde ángulos ligeramente distintos. Esta es la comparación que te falta antes de elegir clave primaria.

El problema del v4: inserciones al azar

Un B-tree mantiene los datos ordenados por clave. Cuando cada nueva fila trae un ID impredecible, su posición de inserción es aleatoria:

  • La página destino puede no estar en memoria → lectura de disco.
  • Puede estar llena → split de página.
  • El buffer pool se llena de páginas "calientes" dispersas que solo se usan una vez.

En PostgreSQL esto tiene nombre conocido: index bloat y write amplification. Con millones de filas diarias, la diferencia frente a IDs secuenciales es medible en órdenes de magnitud de escritura. Los autoincrementales evitaban el problema... a cambio de revelar volumen de negocio en URLs (/pedidos/48392 dice cuántos pedidos llevas) y de requerir coordinación central para asignar IDs.

UUIDv7: timestamp + aleatoriedad

La versión 7 empaqueta un timestamp Unix en milisegundos de 48 bits seguido de 74 bits aleatorios:

018f 6a1c b2d4 7xxx yxxx xxxxxxxxxxxx
└── timestamp ms ──┘└─ rand_a + rand_b ─┘

Las propiedades resultantes:

  • Ordenables cronológicamente: dos v7 generados en momentos distintos ordenan igual como strings y como bytes. ORDER BY idORDER BY created_at sin columna extra.
  • Inserción casi secuencial: los nuevos registros caen siempre "al final" del índice. Adiós splits aleatorios.
  • Únicos sin coordinación: los bits aleatorios garantizan unicidad incluso entre máquinas generando miles por milisegundo.
  • Fecha gratis: decodificar los primeros bytes revela cuándo nació el registro.

Generación nativa ya disponible:

crypto.randomUUID();          // siempre v4 (por ahora)
// v7 con librería o implementación manual:
function uuidv7() {
  const ts = Date.now();
  const bytes = crypto.getRandomValues(new Uint8Array(10));
  const hex = [
    ts.toString(16).padStart(12, "0").slice(0, 12),
    [...bytes].map(b => b.toString(16).padStart(2, "0")).join("")
  ].join("");
  // fija versión 7 y variante según RFC 9562
  return `${hex.slice(0,8)}-${hex.slice(8,12)}-7${hex.slice(13,16)}-a${hex.slice(17,20)}-${hex.slice(20,32)}`;
}

PostgreSQL 18 incluye uuidv7() nativo; las extensiones (pg_uuidv7) y librerías cliente cubren versiones anteriores.

ULID: el primo con Crockford Base32

ULID (Universally Unique Lexicographically Sortable Identifier) resolvió el mismo problema en 2016, con dos diferencias de diseño:

  1. 128 bits igual, pero codifica todo en Crockford Base32 de 26 caracteres: 0123456789ABCDEFGHJKMNPQRSTVWXYZ (sin I, L, O, U para evitar confusiones visuales).
  2. 48 bits de timestamp + 80 de aleatoriedad, sin guiones ni estructura interna visible:
01ARZ3NDEKTSV4RRFFQ69G5FAV

Ventajas prácticas: 26 caracteres frente a 36, ordenable como string en cualquier sistema sin parsear, y más corto en URLs. Desventaja: no es estándar ISO/RFC, así que ecosistemas fuera de JS/Go/Java requieren librería, mientras UUIDv7 es ahora norma internacional con soporte creciente en runtimes y bases de datos.

Comparativa directa

Propiedad UUID v4 UUID v7 ULID
Aleatoriedad 122 bits 74 bits 80 bits
Orden temporal No Sí (ms) Sí (ms)
Tamaño textual 36 chars 36 chars 26 chars
Estándar RFC 9562 RFC 9562 Especificación propia
Fecha embebida No
Soporte nativo DB Universal Creciente Por extensión

Nota sobre los bits perdidos: v7 conserva unicidad estadística sobrada para cualquier carga real; la colisión requiere coincidencia de milisegundo Y de 74 bits aleatorios entre generadores concurrentes. No es un escenario de preocupación práctica.

Cuándo seguir con v4

No todo es migración: tokens opacos de sesión, claves API expuestas, identificadores en contextos donde filtrar por fecha sería información sensible — ahí la ausencia total de estructura del v4 es precisamente la virtud. Un v7 en URLs públicas regala el timestamp de creación.

Y una advertencia de seguridad aplicada: si usas IDs ordenables en endpoints públicos, combina con autorización correcta — el orden no sustituye permisos, solo hace predecibles los vecinos (/facturas/018f6a1c... invita a probar el siguiente).

Genera y verifica identificadores

Nuestro generador de UUID produce v4 y variantes al instante para pruebas, y si necesitas repasar cómo funcionan internamente los v4 con crypto.randomUUID(), tienes la guía completa de UUID en JavaScript.

Preguntas frecuentes

¿Puedo migrar una tabla existente de v4 a v7? Puedes usar v7 para registros NUEVOS sin tocar los viejos: el índice acepta ambos. Reordenar históricos rara vez compensa.

¿UUIDv7 filtra información? Sí, deliberadamente: expone la fecha de creación. Si eso es un problema en tu dominio, quédate en v4.

¿Snowflake IDs (Twitter)? Misma idea (timestamp + worker + secuencia) pero requieren coordinación de worker IDs entre máquinas. v7/ULID logran lo esencial sin esa infraestructura.


Genera identificadores únicos al instante con nuestro generador de UUID online, gratis y directamente en tu navegador.

Pruébalo sin código

Generador de UUID

UUIDs v4 con crypto.randomUUID().

Abrir Generador de UUID

Hecho por

Miguel Ángel Colorado Marin (MACM)

Full-Stack Developer · Guadalajara, España

Desarrollo aplicaciones web, herramientas digitales y proyectos completos — desde el diseño hasta el despliegue.

Contáctame