Generador de UUID
Genera UUID —v4 aleatorios o v7 ordenados por tiempo— de uno en uno o por lotes.
122 bits aleatorios. No revela nada sobre cuándo se creó.
Generando…
Qué es un UUID y por qué existe
Un UUID —Universally Unique Identifier, llamado GUID en la documentación de Microsoft— es un valor de 128 bits escrito como 32 dígitos hexadecimales en la familiar agrupación 8-4-4-4-12. Su propósito entero es permitir que sistemas separados acuñen identificadores de forma independiente, sin coordinación alguna entre ellos, y aun así confiar en que los resultados no colisionarán. Eso es lo que lo distingue de una columna autoincremental: dos servidores, dos clientes móviles sin conexión en un avión y un proceso en segundo plano pueden crear registros en el mismo instante sin pedirle permiso a nadie.
La unicidad aquí es probabilística, no garantizada. La versión 4 deja 122 bits al azar, un espacio lo bastante grande como para que, incluso generando miles de millones de valores, la probabilidad de una repetición siga estando muy por debajo de la de que un disco corrompa los datos en silencio. En la práctica puedes tratarlo como único; las matemáticas no son el eslabón débil.
Versión 4 frente a versión 7: la decisión que importa
La versión 4 es aleatoria de principio a fin. No transporta información alguna: ni cuándo se creó, ni por quién, ni en qué orden. Esa es su mayor virtud o su defecto central, según dónde la pongas.
La versión 7, estandarizada en el RFC 9562 en 2024, sustituye los primeros 48 bits por una marca de tiempo Unix en milisegundos y rellena el resto con aleatoriedad. Como el tiempo va primero y el valor se lee de izquierda a derecha, ordenar identificadores v7 como texto plano también los ordena cronológicamente.
No es una diferencia cosmética. Las bases de datos guardan las claves primarias en un índice B-tree ordenado. Si insertas claves v7, cada fila nueva aterriza en el borde derecho del árbol, junto a la anterior: las páginas en las que escribes permanecen en memoria y el índice crece ordenadamente. Si insertas claves v4, cada escritura cae en una posición aleatoria, la base de datos toca una página distinta cada vez, la tasa de aciertos en caché baja y el índice se fragmenta. En una tabla grande y con mucho tráfico la diferencia de rendimiento en las inserciones es considerable, y por eso v7 se ha adoptado tan rápido para claves primarias.
- Elige v7 para claves primarias, identificadores de eventos y registros, y todo aquello que vayas a ordenar o consultar por rango de fecha de creación.
- Elige v4 cuando el identificador aparezca en un lugar no confiable y no deba filtrar nada, ni siquiera que un registro se creó justo antes que otro.
- Cualquiera de las dos sirve para un ID de correlación, una clave de idempotencia o un nombre de archivo, donde el orden no importa.
La contrapartida es exactamente esa filtración: un identificador v7 le dice a cualquiera que lo vea, al milisegundo, cuándo se creó. Para el ID de una fila eso suele ser inofensivo y a menudo útil. Para un token de restablecimiento de contraseña o un enlace público para compartir es información que no pretendías publicar, y esos no deberían ser UUID en absoluto, sino tokens aleatorios de un generador de secretos específico.
El orden dentro del mismo milisegundo
Una sutileza que se le escapa a muchas implementaciones de v7: el hardware moderno genera muchos más de un identificador por milisegundo. Si dos valores comparten marca de tiempo, su orden lo deciden los bits aleatorios que vienen después, es decir, al azar. Genera cincuenta en un bucle cerrado y obtendrás cincuenta valores solo aproximadamente ordenados, perdiendo justo la propiedad por la que elegiste v7.
El RFC 9562 lo resuelve con un contador monótono, y esta herramienta lo implementa: los 12 bits inmediatamente posteriores a la marca de tiempo cuentan hacia arriba dentro de un milisegundo, de modo que un lote es estrictamente creciente y no solo aproximado. Si el contador se llena —más de 4096 valores en el mismo milisegundo— el generador toma prestado el milisegundo siguiente en lugar de dar la vuelta y emitir un valor que se ordene antes que su predecesor. El reloj yendo hacia atrás, algo que ocurre con las correcciones NTP, se trata igual.
Leyendo un valor v7 de izquierda a derecha, tomando 0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b como ejemplo:
- 0190a1b2-c3d4 — la marca de tiempo Unix de 48 bits en milisegundos. Como va primero, el orden textual es el orden temporal.
- 7 — el dígito de versión, que es lo que hace que esto sea un v7 y no un v4.
- e5f — el contador monótono de 12 bits, que se incrementa dentro de un mismo milisegundo.
- 8 — los bits de variante, fijados por el RFC 9562 para todo UUID moderno (siempre 8, 9, a o b).
- a9b-0c1d2e3f4a5b — los 62 bits restantes, puramente aleatorios.
Almacenar y usar UUID
La forma canónica es en minúsculas y con guiones, y el RFC 9562 dice que los generadores deben emitir exactamente eso, razón por la que esta herramienta no ofrece opciones de formato. Aun así te encontrarás otras grafías: en mayúsculas y entre llaves en las herramientas de Microsoft, y sin guiones donde alguien quiso una columna más corta. Todas son los mismos 128 bits, y las comparaciones deberían ignorar mayúsculas y minúsculas.
Donde de verdad cuenta es en el almacenamiento. Un UUID son 16 bytes, pero su forma textual son 36 caracteres, así que guardarlo como cadena más que duplica el espacio en la fila y, más importante, en todos los índices que lo incluyan. Usa un tipo nativo donde exista:
uuid -- PostgreSQL: tipo nativo de 16 bytes BINARY(16) -- MySQL: compacto; CHAR(36) desperdicia 20 bytes por fila uniqueidentifier -- SQL Server crypto.randomUUID() // JavaScript: solo v4, requiere contexto seguro uuid.uuid4() / uuid7() # Python: v4 en la biblioteca estándar; v7 con una librería
Una última advertencia: un UUID identifica, no autoriza. Como no se pueden adivinar, resulta tentador tratar una URL no listada que contenga uno como si fuera privada. Pero los identificadores se filtran —por registros, historial del navegador, cabeceras referrer y capturas de pantalla—, así que todo lo que realmente necesite protección sigue necesitando una comprobación de permisos detrás.
Preguntas frecuentes
- ¿Debería usar v4 o v7?
- Usa v7 para claves primarias y todo lo que vayas a ordenar por fecha de creación: la marca de tiempo inicial mantiene las inserciones agrupadas al final del índice en lugar de dispersas por él. Usa v4 cuando el identificador no deba revelar nada en absoluto, ni siquiera cuándo se creó.
- ¿Pueden repetirse dos UUID?
- Es posible, pero increíblemente improbable. La versión 4 tiene 122 bits aleatorios, así que incluso tras generar miles de millones de valores la probabilidad de colisión sigue muy por debajo de la de que el almacenamiento los corrompa en silencio.
- ¿Qué pasó con las versiones 1, 3 y 5?
- La versión 1 codifica una marca de tiempo y la dirección MAC de la máquina, lo que filtra la identidad del hardware y ni siquiera puede producirse en un navegador. Las versiones 3 y 5 derivan un UUID de forma determinista a partir de un espacio de nombres y un nombre usando MD5 o SHA-1: útil cuando la misma entrada debe dar siempre el mismo identificador, pero es otra tarea distinta de generar uno nuevo.
- ¿Es un UUID lo bastante seguro como token secreto?
- Un UUID v4 no se puede adivinar, pero uno v7 codifica abiertamente su hora de creación, y ninguno está pensado como credencial. Para restablecimientos de contraseña, tokens de sesión o enlaces compartidos, genera un secreto aleatorio específico y comprueba permisos en el servidor en vez de confiar en que el identificador sea difícil de adivinar.
- ¿Por qué mi lote de v7 no sale perfectamente ordenado en otras herramientas?
- Porque muchas implementaciones se saltan el contador monótono. Cuando varios valores comparten milisegundo, su orden queda en manos de los bits aleatorios que siguen. Esta herramienta implementa el contador del RFC 9562, así que un lote generado aquí es estrictamente creciente.
- ¿Cómo debería guardar un UUID en una base de datos?
- En un tipo nativo de 16 bytes donde exista: uuid en PostgreSQL, uniqueidentifier en SQL Server, BINARY(16) en MySQL. Guardar en su lugar la forma textual de 36 caracteres más que duplica el espacio usado en la fila y en cada índice que incluya la columna.
- ¿Se generan en vuestros servidores?
- No. Se generan en tu navegador con crypto.getRandomValues, la fuente criptográfica de aleatoriedad de la plataforma, la misma que usa crypto.randomUUID. Ningún valor se envía a ninguna parte, y recargar la página produce un conjunto completamente nuevo.