¿Qué es un UUID?
Un UUID (Universally Unique Identifier, Identificador Universalmente Único), conocido en terminología de Microsoft como GUID (Globally Unique Identifier), es un número de 128 bits utilizado para identificar información de forma única en sistemas informáticos. A diferencia de los enteros de autoincremento, que requieren una autoridad central para asignar el siguiente valor, los UUID pueden generarse de forma independiente por cualquier máquina, en cualquier momento, con una probabilidad de colisión astronómicamente baja.
La representación textual estándar de un UUID tiene el siguiente aspecto:
550e8400-e29b-41d4-a716-446655440000
^^^^^^^^ ^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^
tiempo tiempo versión variante nodo
Esa cadena con guiones codifica 32 dígitos hexadecimales (128 bits) en el formato xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx, donde:
- M es el dígito de versión (1, 3, 4, 5 o 7)
- N es el nibble de variante (8, 9, a o b para UUID conformes con RFC 4122)
Breve Historia
El concepto de identificador universalmente único se originó en Apollo Computer y Digital Equipment Corporation (DEC) a finales de la década de 1980, como parte del Sistema de Computación en Red (NCS) y el Entorno de Computación Distribuida (DCE). El objetivo era permitir que los sistemas distribuidos crearan identificadores sin ningún registro central.
Microsoft adoptó el concepto para COM/OLE y lo llamó GUID, pero la estructura subyacente es idéntica a un UUID. Los dos términos son intercambiables en la práctica.
La especificación formal llegó con RFC 4122, publicada en julio de 2005 por el IETF. Estandarizó cinco versiones de UUID (v1–v5) y definió los bits de variante. Dos décadas después, RFC 9562 (publicada en mayo de 2024) reemplazó a RFC 4122 y añadió oficialmente UUID v6 y v7, que abordan las deficiencias de rendimiento en bases de datos de las versiones anteriores.
Estructura del UUID: 128 Bits Explicados
Un UUID siempre ocupa exactamente 128 bits (16 bytes). Cuando se formatea como cadena, tiene 36 caracteres (32 dígitos hexadecimales + 4 guiones).
Campo Bits Dígitos hex Descripción
────────────────────────────────────────────────────────────
time_low 32 8 32 bits bajos del timestamp (v1)
time_mid 16 4 16 bits medios del timestamp (v1)
time_hi_and_version 16 4 12 bits altos del timestamp + versión de 4 bits
clock_seq_hi_res 8 2 Bits de variante + secuencia de reloj alta
clock_seq_low 8 2 Secuencia de reloj baja
node 48 12 ID de nodo (dirección MAC en v1, random en otros)
La versión se codifica en los 4 bits más significativos del campo time_hi_and_version (el 13.° carácter hexadecimal). La variante se codifica en los 2–3 bits más significativos de clock_seq_hi_res (el 17.° carácter hexadecimal).
Versiones de UUID Explicadas
Versión 1 — Basada en Tiempo
UUID v1 combina un timestamp de 60 bits (intervalos de 100 nanosegundos desde el 15 de octubre de 1582) con la dirección MAC del host y una secuencia de reloj.
Ejemplo: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
Ventajas: Contiene información temporal, lo que permite ordenarlos aproximadamente por tiempo de creación.
Desventajas: Incrusta la dirección MAC, lo que plantea problemas de privacidad: puede revelar cuándo y dónde se generó el UUID. No se recomienda para identificadores públicos.
Versión 2 — Seguridad DCE
UUID v2 reemplaza parte del timestamp con un UID/GID POSIX y un identificador de dominio. Está definido en la especificación DCE 1.1 pero rara vez se usa en la práctica, ya que sacrifica las garantías de unicidad para incrustar el dominio.
Versión 3 — Basada en Nombre (MD5)
UUID v3 genera un UUID determinista a partir de un UUID de espacio de nombres y un nombre, haciéndolos hash con MD5.
Ejemplo: 5df41881-3aed-3515-88a7-2f4a814cf09e (espacio de nombres DNS + "example.com")
Caso de uso: Identificadores estables y reproducibles para el mismo recurso lógico. Si se hace hash del mismo espacio de nombres y nombre dos veces, siempre se obtiene el mismo UUID.
Precaución: MD5 es criptográficamente débil. Se prefiere v5 para sistemas nuevos.
Versión 4 — Aleatoria (La Más Popular)
UUID v4 utiliza 122 bits de datos aleatorios criptográficamente seguros (los 6 bits restantes se utilizan para la versión y la variante).
Ejemplo: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d
Esta es por mucho la versión de UUID más utilizada. No requiere coordinación, acceso a red ni conocimiento del host. La aleatoriedad proviene de un CSPRNG (generador de números pseudoaleatorios criptográficamente seguro).
Versión 5 — Basada en Nombre (SHA-1)
UUID v5 es idéntico en concepto a v3 pero utiliza SHA-1 en lugar de MD5.
Ejemplo: 886313e1-3b8a-5372-9b90-0c9aee199e5d (espacio de nombres DNS + "example.com")
Caso de uso: Cuando se necesitan UUID deterministas y reproducibles y se quiere un hash más fuerte que MD5. SHA-1 no es completamente seguro para todos los propósitos criptográficos, pero su resistencia a colisiones es significativamente mejor que MD5.
Versión 7 — Ordenada por Tiempo (Recomendada para Bases de Datos)
UUID v7 es la estrella de RFC 9562. Incrusta un timestamp Unix de 48 bits en milisegundos en los bits más significativos, haciendo que el UUID sea k-ordenable: los UUID generados posteriormente se ordenan después de los UUID generados anteriormente.
Ejemplo: 018e8f5a-2b3c-7d4e-8f9a-0b1c2d3e4f50
Los primeros 12 caracteres hexadecimales (018e8f5a-2b3c) codifican el timestamp en milisegundos. El resto es aleatorio. Esto hace que v7 sea ideal como clave primaria de base de datos: retiene la unicidad global de v4 al tiempo que está ordenada por inserción, lo que reduce drásticamente la fragmentación del índice B-tree.
Probabilidad de Colisión: El Problema del Cumpleaños
UUID v4 usa 122 bits de aleatoriedad. La probabilidad de colisión se puede estimar usando la fórmula del problema del cumpleaños:
p(n) ≈ 1 − e^(−n²/2N)
donde N = 2^122 ≈ 5.32 × 10^36 (total de UUID posibles).
Para tener una probabilidad del 50% de al menos una colisión, necesitarías generar aproximadamente 2.71 × 10^18 (2.71 trillones) de UUID. A una velocidad de 1.000 millones de UUID por segundo, eso llevaría unos 86 años.
Para propósitos prácticos, las colisiones de UUID v4 son tan improbables que pueden tratarse como imposibles en cualquier aplicación del mundo real.
UUID vs. IDs de Autoincremento
| Característica | UUID v4 | Autoincremento |
|---|---|---|
| Alcance de unicidad | Global | Local (por tabla) |
| Lugar de generación | Lado del cliente | Lado del servidor |
| Predecibilidad | No predecible | Secuencial |
| Seguridad en URL | Sí (con codificación) | Sí |
| Rendimiento índice DB | Bajo (aleatorio) | Excelente (secuencial) |
| Fusión/replicación | Fácil | Propenso a conflictos |
| Tamaño de almacenamiento | 16 bytes (binario) | 4–8 bytes |
| Legibilidad humana | Baja | Alta |
| Seguridad (enumeración) | Seguro | Vulnerable |
Los IDs de autoincremento son perfectamente válidos para aplicaciones de base de datos única sin requisitos distribuidos. Los UUID destacan cuando:
- Múltiples servicios o bases de datos necesitan generar IDs de forma independiente.
- Los registros pueden fusionarse de diferentes fuentes.
- Se quiere evitar exponer IDs secuenciales en URLs (ataques de enumeración).
Rendimiento en Base de Datos: v4 vs. v7
El Problema con UUID v4 en Bases de Datos
Debido a que UUID v4 es aleatorio, cada nueva fila se inserta en una posición aleatoria en el índice B-tree. Esto provoca:
- División de páginas de índice — la base de datos debe dividir frecuentemente las páginas del índice para acomodar inserciones fuera de orden.
- Thrashing de caché — los patrones de acceso aleatorios deshabilitan el grupo de búferes, causando frecuentes lecturas de disco.
- Amplificación de escritura — significativamente más E/S que las inserciones secuenciales.
Los benchmarks en tablas grandes (>10M filas) frecuentemente muestran que las claves primarias UUID v4 tienen un rendimiento 3–5 veces peor que las claves secuenciales para cargas de trabajo con muchas inserciones.
UUID v7 Resuelve Esto
UUID v7 es monótonamente creciente dentro de la misma ventana de milisegundos. Los nuevos registros se insertan al final o cerca del final del índice, similar al autoincremento. El resultado es:
- Fragmentación de índice casi nula.
- Utilización óptima del grupo de búferes.
- Rendimiento de inserción comparable al autoincremento.
Recomendación: Usa UUID v7 para cualquier nuevo esquema de base de datos que necesite claves primarias globalmente únicas.
Casos de Uso en Sistemas Distribuidos
Los UUID son la columna vertebral de la identidad distribuida:
- Microservicios: Cada servicio puede generar IDs de forma independiente sin comunicarse con un servidor de secuencias central.
- Event sourcing: Los eventos obtienen IDs inmutables que permanecen únicos a través de reproducciones y rehidrataciones.
- CQRS: Los comandos y consultas pueden correlacionarse mediante un UUID generado en el cliente.
- Bases de datos multi-región: Los registros creados en diferentes regiones nunca chocan, haciendo triviales la consistencia eventual y las operaciones de fusión.
- Claves de idempotencia: Las APIs pueden usar UUIDs generados por el cliente como claves de idempotencia para reintentar solicitudes de forma segura.
- Sistemas de contenido direccionable: UUID v3/v5 pueden producir identificadores estables para el mismo recurso entre sistemas.
ULID: Una Alternativa Moderna
ULID (Universally Unique Lexicographically Sortable Identifier) es una alternativa desarrollada por la comunidad al UUID que es segura para URLs por defecto y siempre ordenable.
| Característica | UUID v4 | UUID v7 | ULID |
|---|---|---|---|
| Ordenable | No | Sí | Sí |
| Seguro para URL | Con codificación | Con codificación | Sí (Crockford Base32) |
| Componente de tiempo | No | Sí (ms) | Sí (ms) |
| Estándar | RFC 9562 | RFC 9562 | Especificación comunitaria |
| Longitud del formato | 36 chars | 36 chars | 26 chars |
| Monótono dentro del ms | No | Opcional | Sí |
ULID tiene el aspecto 01ARZ3NDEKTSV4RRFFQ69G5FAV — 26 caracteres, sin guiones, seguro para usar directamente en URLs. Si necesitas ordenabilidad y seguridad en URLs sin preocuparte por la compatibilidad con RFC, ULID vale la pena considerarlo.
Generación de UUID en Diferentes Lenguajes
JavaScript / TypeScript (Node.js y Navegador)
import { v4 as uuidv4, v7 as uuidv7 } from 'uuid';
const randomId = uuidv4(); // "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
const sortableId = uuidv7(); // "018e8f5a-2b3c-7d4e-8f9a-0b1c2d3e4f50"
// crypto nativo (Node 14.17+ / navegadores modernos)
const nativeId = crypto.randomUUID(); // UUID v4
Python
import uuid
# v4 — aleatorio
print(uuid.uuid4()) # "f47ac10b-58cc-4372-a567-0e02b2c3d479"
# v5 — determinista desde espacio de nombres + nombre
print(uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com'))
# "886313e1-3b8a-5372-9b90-0c9aee199e5d"
Go
import "github.com/google/uuid"
id := uuid.New() // UUID v4
v7, _ := uuid.NewV7() // UUID v7 (google/uuid v1.6+)
fmt.Println(id.String())
Java
import java.util.UUID;
UUID v4 = UUID.randomUUID();
System.out.println(v4); // "3e4666bf-d5e5-4aa7-b8ce-cefe41c7568a"
Rust
use uuid::Uuid;
let v4 = Uuid::new_v4();
let v7 = Uuid::now_v7();
println!("{}", v4);
println!("{}", v7);
Mejores Prácticas
- Usa v4 para identificadores únicos de propósito general donde el ordenamiento no importa.
- Usa v7 para claves primarias de bases de datos para evitar la fragmentación del índice y obtener orden natural de clasificación.
- Usa v5 para IDs deterministas cuando necesitas que la misma entrada siempre produzca el mismo UUID (por ejemplo, deduplicar contenido por URL).
- Evita v1 en contextos sensibles a la privacidad — incrusta tu dirección MAC y tiempo de creación.
- Almacena UUIDs como binario (16 bytes) en la base de datos, no como varchar(36), para ahorrar espacio y mejorar el rendimiento del índice.
- Nunca uses v2 a menos que estés implementando específicamente DCE Security.
- Valida los UUID de entrada en los límites de la API para prevenir la inyección de identificadores malformados.
- Usa una biblioteca bien probada en lugar de implementar tu propia generación de UUID — la fuente de entropía es fácil de implementar mal.
Preguntas Frecuentes
P: ¿Son lo mismo UUID y GUID?
R: Funcionalmente, sí. GUID es el nombre de Microsoft para el mismo formato de identificador de 128 bits. La estructura es idéntica; solo difiere la terminología.
P: ¿Pueden dos UUID ser iguales?
R: En teoría sí, pero la probabilidad es insignificante para v4. Necesitarías generar 2.71 trillones de UUID para tener una probabilidad del 50% de una sola colisión. En la práctica, nunca encontrarás una colisión.
P: ¿Qué versión de UUID debo usar para claves primarias de bases de datos?
R: UUID v7 es la mejor opción. Es ordenado por tiempo (bueno para índices B-tree), globalmente único y estandarizado en RFC 9562. Si tu biblioteca aún no admite v7, usa un ULID o un patrón "COMB" UUID como alternativa.
P: ¿Es UUID v4 suficientemente seguro para usar como token de sesión?
R: UUID v4 tiene 122 bits de aleatoriedad, lo que generalmente es suficiente. Sin embargo, las bibliotecas de tokens de sesión dedicadas pueden usar ligeramente más entropía o mejores codificaciones. Para contextos de alta seguridad, prefiere un generador de tokens dedicado.
P: ¿Cómo almaceno un UUID eficientemente en una base de datos SQL?
R: Usa un tipo de columna UUID nativo si está disponible (PostgreSQL, MySQL 8+), o una columna BINARY(16). Evita CHAR(36) / VARCHAR(36), que ocupa 2.25 veces más espacio y es más lento de indexar.
P: ¿Cuál es la diferencia entre UUID v3 y v5?
R: Ambos son basados en nombre y deterministas. v3 usa MD5; v5 usa SHA-1. SHA-1 tiene mejor resistencia a colisiones, por lo que se prefiere v5 para sistemas nuevos. Ninguno debe usarse para hashing crítico de seguridad.
P: ¿Reemplaza UUID v7 a UUID v4?
R: Para claves primarias de bases de datos, sí — v7 es estrictamente mejor. Para otros casos de uso (por ejemplo, claves de API, tokens, IDs de correlación) donde el ordenamiento es irrelevante, v4 sigue siendo perfectamente válido.
Resumen
Los UUID son un primitivo fundamental en la ingeniería de software moderna. Entender las diferencias entre versiones ayuda a tomar la decisión correcta:
- v4 — mejor para unicidad general sin coordinación.
- v5 — mejor para identificadores deterministas y reproducibles.
- v7 — mejor para claves primarias de bases de datos debido al ordenamiento temporal.
Ya sea que estés construyendo un monolito, una arquitectura de microservicios o una base de datos distribuida globalmente, los UUID proporcionan una forma probada en batalla y estandarizada de identificar tus datos de forma única y segura.