Generador de UUID
Genere UUID v4 o v7 ordenados por tiempo e inspeccione cualquier UUID que ya tenga.
UUID aleatorios
Analizar un UUID
Pega uno para ver de qué versión es y qué lleva incrustado, si es que lleva algo.
Las versiones, y cuáles dos importan
Hay ocho, y para trabajo nuevo la elección está en realidad entre dos. Las demás conviene reconocerlas cuando te tropiezas con una en un sistema antiguo.
| Versión | Se construye con | Úsala cuando |
|---|---|---|
| v4 | 122 bits aleatorios | Necesitas que sea imposible de adivinar. La opción por defecto para tokens e identificadores. |
| v7 | Marca de tiempo + aleatoriedad | Necesitas una clave de base de datos. Se ordena por hora de creación. |
| v1 | Marca de tiempo + dirección MAC | Heredada. Filtra la máquina y la hora. |
| v3 / v5 | Hash de un espacio de nombres y un nombre | Necesitas que la misma entrada dé siempre el mismo ID. |
| v6 | v1, reordenada | Migras datos v1 y quieres que se ordenen. |
| v8 | Lo que tú decidas | Casi nunca. |
El problema del índice, que es la verdadera razón de que exista v7
Este es el argumento práctico, y vale la pena entenderlo en vez de aceptarlo por fe.
Una clave primaria de base de datos se guarda en un árbol B, ordenada. Inserta enteros consecutivos y cada fila nueva aterriza en el borde derecho: una página se mantiene caliente en memoria, el árbol crece de forma ordenada y las escrituras salen baratas.
Inserta UUID v4 y cada fila aterriza en un sitio aleatorio. Se tocan páginas por todo el árbol, cada una hay que leerla antes de poder escribirla, y las páginas se parten según se llenan. En una tabla de cierto tamaño, el rendimiento de inserción baja de forma apreciable y el índice se fragmenta: el efecto está bien documentado y es lo que les dio mala fama a las claves UUID.
La v7 lo arregla poniendo la marca de tiempo delante. Genera unas cuantas ahí arriba con v7 seleccionado y fíjate en el prefijo compartido: los valores creados cerca en el tiempo quedan contiguos, así que las inserciones se añaden al final del índice como si fueran enteros y a la vez siguen siendo únicas en todo el mundo. Conservas la propiedad que hacía atractivos a los UUID —generar un ID en cualquier parte, sin coordinación— sin pagarla en cada escritura.
Con precisión: el orden está garantizado entre milisegundos, no dentro de uno. Dos UUID v7 generados en el mismo milisegundo se ordenan por sus colas aleatorias, algo que el RFC 9562 permite y que además deja a las implementaciones afinar con un contador. No cambia nada en el argumento de la localidad del índice, que solo depende de la marca de tiempo inicial.
El coste que queda para ambos: 16 bytes frente a 4 u 8, replicados en todos los índices que referencian la clave. En una tabla grande con varias claves externas, eso es disco de verdad.
Qué revela la v7
La marca de tiempo la puede leer cualquiera que tenga el identificador. Pega un UUID v7 en el analizador de arriba y te dirá el milisegundo en que se creó.
Normalmente es inofensivo. De vez en cuando no lo es: un identificador v7 en una URL pública revela cuándo se creó un registro, lo que puede bastar para deducir ritmos de alta, volúmenes de pedidos o que un documento se fechó hacia atrás. Si eso importa, la división sencilla es v4 para todo lo que vea el usuario y v7 para las claves internas.
Dónde la aleatoriedad tiene que ser de verdad
La aritmética de colisiones que todo el mundo cita —2,7 trillones antes de que haya una probabilidad del 50 % de una colisión— da por hecho 122 bits genuinamente aleatorios. Es una afirmación sobre el formato, no sobre tu implementación.
Un UUID construido con Math.random() no tiene ni la entropía ni la imprevisibilidad que ese número sugiere, y las colisiones en el mundo real han sido esencialmente siempre esto y no mala suerte. Dos procesos arrancados en el mismo segundo con la misma semilla producen la misma secuencia.
Esta página usa crypto.randomUUID() donde existe y crypto.getRandomValues en caso contrario. Vale la pena mirar qué usa tu propio código, sobre todo si los UUID hacen las veces de tokens: un identificador predecible para restablecer contraseñas es un secuestro completo de la cuenta.
Guardarlos de forma eficiente
La forma de texto de 36 caracteres es cómoda y derrochadora. Las alternativas, todas con los mismos 128 bits:
- Tipo UUID nativo: Postgres tiene uno y guarda 16 bytes. Úsalo.
- `BINARY(16)`: el equivalente en MySQL, más o menos la mitad del almacenamiento de
CHAR(36). - Base64: 22 caracteres, cuando tiene que ser texto y la longitud importa.
- Base32: 26 caracteres, sin distinguir mayúsculas, que es lo que quieres si alguna vez una persona va a leer uno en voz alta.
Relacionado
Para secretos que tiene que teclear una persona y no guardar una máquina, el generador de contraseñas usa la misma fuente aleatoria. Para leer la marca de tiempo de un UUID v7 en otro formato, el conversor de marcas de tiempo sigue a partir de ahí.
Preguntas sobre UUID
¿Pueden chocar dos UUID?
En principio sí; en la práctica no, siempre que la aleatoriedad sea real. Un UUID v4 tiene 122 bits aleatorios, y necesitaría generar alrededor de 2,7 quintillones de ellos antes de alcanzar una probabilidad del 50% de una sola colisión: aproximadamente mil millones por segundo durante 85 años. El fracaso realista nunca son las matemáticas: es una fuente aleatoria débil. Un UUID creado en Math.random() o en un PRNG mal sembrado puede colisionar y colisiona, razón por la cual esta página utiliza la fuente criptográfica del navegador.
¿Debo utilizar un UUID como clave principal de la base de datos?
Depende de la versión y la diferencia es grande. Un UUID v4 es aleatorio, por lo que las inserciones consecutivas aterrizan en puntos aleatorios en un índice de árbol B: las páginas se dividen, el índice se fragmenta y el rendimiento de escritura cae considerablemente en una tabla grande. Un UUID v7 comienza con una marca de tiempo de milisegundos, por lo que las inserciones se agregan al final como un entero de incremento automático manteniendo la unicidad global. Si desea claves UUID, utilice v7. El otro coste se aplica a ambos: 16 bytes frente a 4 u 8 para un número entero, en cada índice que hace referencia a él.
¿Qué es UUID v7? ¿Es seguro usarlo todavía?
Ordenado en el tiempo: 48 bits de milisegundos Unix seguidos de 74 bits aleatorios, estandarizado en RFC 9562 en mayo de 2024. Es un estándar publicado con soporte en Postgres actual, en la mayoría de ecosistemas de lenguajes y en un buen número de bibliotecas. Es un valor predeterminado razonable para trabajos nuevos. La única propiedad a tener en cuenta es que incorpora una hora de creación, por lo que un identificador v7 en una URL revela aproximadamente cuándo se realizó el registro.
¿Es un UUID lo suficientemente seguro como para usarlo como token?
Un UUID v4 de una fuente criptográfica tiene 122 bits de entropía, lo cual es más que adecuado para un enlace de restablecimiento de contraseña o un identificador de sesión. Dos advertencias. En primer lugar, la fuente tiene que ser criptográfica: crypto.randomUUID lo es, la mayoría de las implementaciones de bibliotecas lo son, y cualquier cosa construida sobre Math.random() no lo es. En segundo lugar, otras versiones no son adecuadas: la v1 incorpora una marca de tiempo e históricamente una dirección MAC, la v3 y la v5 son hashes deterministas de sus entradas y la v7 revela su hora de creación. Si debe ser imposible de adivinar, utilice v4.
¿Por qué un UUID tiene 36 caracteres cuando solo tiene 16 bytes?
Porque está escrito en hexadecimal (dos caracteres por byte, es decir, 32) más cuatro guiones. En su lugar, algunos sistemas almacenan los 16 bytes sin formato, que es para lo que sirve MySQL BINARY(16) y aproximadamente reduce a la mitad el almacenamiento. Otros utilizan una codificación de texto más corta: Base64 proporciona 22 caracteres, Base32 proporciona 26 y no distingue entre mayúsculas y minúsculas. Todos ellos son los mismos 128 bits con ropa diferente.
Última revisión . ¿Has visto algo desactualizado? Dínoslo.
