¿Qué es un ULID y cómo funciona esta página?
ULID son las siglas de Universally Unique Lexicographically Sortable Identifier. Cada ULID es una cadena de 26 caracteres que codifica 128 bits de información: los primeros 10 caracteres representan una marca de tiempo con precisión de milisegundos (48 bits) y los 16 restantes un componente aleatorio (80 bits). La página te permite seleccionar el formato ULID, elegir entre 1 y 100 identificadores y generarlos al instante. El resultado es una lista de cadenas listas para copiar individualmente o todas juntas. A diferencia de otros formatos disponibles en la misma herramienta, ULID no ofrece palancas para mayúsculas o guiones porque el formato es inherentemente insensible a mayúsculas y carece de guiones. El generador utiliza crypto.getRandomValues() del navegador, por lo que toda la creación ocurre localmente y no se envía nada a ningún servidor. Los mensajes de estado son "Listo.", "Generados." y "¡Copiados todos!" cuando se copia la lista completa.
Estructura interna de un ULID: marca de tiempo y componente aleatorio
Un ULID se construye concatenando dos partes: una marca de tiempo de 48 bits codificada en los primeros 10 caracteres y un valor aleatorio de 80 bits en los 16 caracteres restantes. La marca de tiempo cuenta los milisegundos desde el 1 de enero de 1970 (época Unix) y permite ordenar los ULID cronológicamente. El componente aleatorio se genera con crypto.getRandomValues(), una fuente criptográficamente fuerte disponible en todos los navegadores modernos. Al tratarse de 80 bits, el espacio de posibles sufijos aleatorios es de 2^80, lo que ofrece una probabilidad de colisión extremadamente baja incluso cuando se generan muchos identificadores en el mismo milisegundo.
La codificación de ambos campos utiliza el alfabeto Crockford Base32, que asigna 5 bits por carácter. Así, 48 bits requieren 10 caracteres (10 × 5 = 50 bits; sobran 2 bits que se descartan). De forma análoga, 80 bits necesitan 16 caracteres (16 × 5 = 80 bits). El alfabeto completo es: 0123456789ABCDEFGHJKMNPQRSTVWXYZ. En ULID, siempre se usa la versión en mayúsculas en la representación canónica, pero la página las genera en mayúsculas y el receptor debe tratarlas como insensibles a mayúsculas (una ULID "01ARZ3NDEKTSV4RRFFQ69G5FAV" y "01arz3ndektsv4rrffq69g5fav" son equivalentes).
El alfabeto Crockford Base32 y por qué importa
El alfabeto Crockford fue diseñado para evitar confusiones visuales: excluye las letras I, L, O y U porque se prestan a confusión con el 1, el 0 y otras letras. Tampoco incluye la letra U para evitar que se confunda con V. El resultado es un conjunto de 32 símbolos (0-9 y 22 letras) que son inequívocos incluso cuando se transcriben a mano. Además, al ser insensible a mayúsculas, se reduce el riesgo de errores tipográficos en entradas de usuario o en logs.
Para la página esto significa que no tiene que ofrecer un interruptor de "mayúsculas/minúsculas" ni añadir guiones para facilitar la lectura. El ULID se presenta tal cual, sin adornos. Cada carácter se puede copiar individualmente al hacer clic sobre él, y al copiar la lista completa se obtienen 26 caracteres por línea sin separadores adicionales.
ULID frente a UUID: diferencias clave en longitud, ordenación y legibilidad
La comparación directa es con UUID v4 (36 caracteres con guiones, 122 bits aleatorios) y UUID v7 (también 36 caracteres, pero con 48 bits de tiempo y 74 bits aleatorios). ULID reduce la representación en 10 caracteres (de 36 a 26) porque usa Crockford Base32 en lugar de hexadecimal con guiones.
| Característica | UUID v4 (hexadecimal con guiones) | ULID (Crockford Base32) |
|---|---|---|
| Longitud | 36 caracteres | 26 caracteres |
| Bits de tiempo | 0 (totalmente aleatorio) | 48 (marca Unix en ms) |
| Bits aleatorios | 122 | 80 |
| Ordenación cronológica | No | Sí, lexicográfica |
| Sensible a mayúsculas | Sí (habitualmente en minúsculas) | No (insensible) |
| Guiones | Sí (4 guiones) | No |
| Caracteres seguros URL | Sí, pero requiere codificación en algunos casos | Todos los caracteres son seguros por defecto |
La principal ventaja práctica del ULID es la ordenación por tiempo. Si almacenas ULID como clave primaria en una base de datos B-tree (por ejemplo, PostgreSQL con tipo text o bytea), los nuevos registros se insertan aproximadamente al final del índice, reduciendo la fragmentación y mejorando el rendimiento de escritura frente a un UUID v4 completamente aleatorio. Sin embargo, esto no es una garantía de orden estricto: dos ULID generados en el mismo milisegundo pueden aparecer en cualquier orden porque la parte aleatoria no tiene relación con el tiempo.
Ordenación temporal y probabilidad de colisión
La marca de tiempo de 48 bits proporciona una resolución de 1 milisegundo y cubre aproximadamente 8.925 años desde la época Unix (2^48 milisegundos ≈ 8,9 × 10^6 segundos / 86400 ≈ 8.925 años). Superado ese rango, la marca de tiempo se desbordaría (algo irrelevante para aplicaciones actuales). Dentro del mismo milisegundo, los ULID no ofrecen orden garantizado; la única forma de obtener un orden estricto sería añadir un contador monotónico, pero la especificación original de ULID no lo exige.
La probabilidad de colisión depende únicamente de los 80 bits aleatorios, ya que la parte temporal es única si los relojes están sincronizados (en un solo generador). Si generas 1.000 ULID por segundo durante un año (≈ 3,16 × 10^10 IDs), la probabilidad de al menos una colisión es inferior a 10^-12 según la aproximación del cumpleaños (tasa de ~2,7 × 10^-12 para 2^80 y ese número de muestras). En la práctica, con la generación local en el navegador, el riesgo es insignificante para cualquier aplicación no astronómica.
Seguridad en URL y generación local en el navegador
Todos los caracteres de Crockford Base32 (0-9, A-Z excepto I, L, O, U) son caracteres no reservados según RFC 3986. Eso significa que un ULID puede incluirse en una URL sin necesidad de porcentualizar (escapar) ningún carácter. No hay guiones ni puntos que puedan confundir a los routers o analizadores de rutas. Por ejemplo, https://ejemplo.com/item/01ARZ3NDEKTSV4RRFFQ69G5FAV funciona sin modificaciones.
La generación ocurre íntegramente en el navegador mediante crypto.getRandomValues(), una API criptográfica estándar. No se realiza ninguna petición a un servidor, lo que preserva la privacidad del usuario y evita latencias de red. Al cambiar cualquiera de las opciones (formato, cantidad) se regenera la lista completa de IDs. El límite de 100 identificadores por lote evita sobrecargar la interfaz y es suficiente para la mayoría de los casos de uso.
Preguntas frecuentes (FAQ)
1. ¿Puedo generar menos de 1 ULID?
No, el valor mínimo es 1. El campo de cantidad solo acepta números enteros entre 1 y 100.
2. ¿Qué ocurre si cambio el formato después de generar ULID?
Al cambiar cualquier opción (formato, cantidad) se regenera la lista inmediatamente con el nuevo formato. No se guarda el listado anterior.
3. ¿Los ULID generados son verdaderamente aleatorios?
Sí, el componente aleatorio se obtiene de crypto.getRandomValues() que usa una fuente criptográficamente segura del sistema operativo. No se emplean generadores pseudoaleatorios débiles.
4. ¿Por qué no veo opciones para mayúsculas o guiones en ULID?
Porque ULID se define como un formato insensible a mayúsculas y sin guiones. Añadirlos iría contra la especificación y restaría interoperabilidad.
5. ¿Puedo usar estos ULID como claves primarias en bases de datos?
Sí, muchos sistemas los aceptan como cadenas. La ordenación lexicográfica mejora el rendimiento en índices B-tree respecto a UUID aleatorios, pero no es un orden estricto dentro del mismo milisegundo.
6. ¿Los ULID se pueden convertir a UUID?
No directamente, porque la codificación es diferente. Un ULID de 26 caracteres en Base32 representa 128 bits; para convertirlo a UUID necesitarías reinterpretar esos 128 bits como dos grupos de 64 bits y representarlos en hexadecimal con guiones, pero perderías la semántica de tiempo. No es una operación estándar.