Generador ULID
Genera identificadores únicos ordenables lexicográficamente
Haz clic en Generar para crear ULIDs
¿Qué es un ULID?
ULID (Identificador Universalmente Único Lexicográficamente Ordenable) es un formato de identificador de 128 bits diseñado para ser tanto único como naturalmente ordenable. A diferencia de UUID v4, que es completamente aleatorio, un ULID incorpora una marca de tiempo Unix con precisión de milisegundos en sus bits más significativos — asegurando que los IDs generados más tarde se ordenen después de los generados antes.
Los ULIDs se codifican usando el alfabeto Crockford Base32, produciendo una cadena compacta de 26 caracteres que es segura para URL, insensible a mayúsculas y libre de caracteres visualmente ambiguos.
La especificación ULID fue creada por Alizain Feerasta y es ampliamente utilizada en sistemas distribuidos, event sourcing y claves primarias de bases de datos donde importan tanto la unicidad como el ordenamiento temporal. Los ULIDs no son un estándar IETF — son una especificación comunitaria disponible en ulid.github.io.
Estructura ULID
Un ULID tiene 128 bits de ancho, dividido en dos componentes:
| Marca de Tiempo | Aleatorio |
|---|---|
| 01ARZ3NDEK | TSVE4RRFFQ69G5FAV |
| 48 bits — marca de tiempo Unix en milisegundos. Codifica el tiempo de generación con precisión de 1 ms. Cubre fechas hasta el año 10889. | 80 bits — datos aleatorios criptográficamente seguros. Regenerados de forma fresca para cada ULID (a menos que se use el modo de monotonía). |
Codificado como 26 caracteres Crockford Base32: los primeros 10 caracteres representan la marca de tiempo, los últimos 16 representan el componente aleatorio.
Alfabeto Crockford Base32
Los ULIDs usan la codificación Crockford Base32, que usa 32 de los 36 caracteres alfanuméricos. El alfabeto es: 0123456789ABCDEFGHJKMNPQRSTVWXYZ
Cuatro caracteres se excluyen intencionalmente:
IyLse excluyen — fácilmente confundidos con el dígito1Ose excluye — fácilmente confundida con el dígito0Use excluye — evita palabras obscenas accidentales en los IDs generados- La codificación es
insensible a mayúsculas—01ARZ3NDEKTSV4RRFFQ69G5FAVy01arz3ndektsv4rrffq69g5favson el mismo ULID
Crockford Base32 es más eficiente que el hexadecimal (32 símbolos vs 16) y más legible para humanos que Base64 (sin caracteres + / =, insensible a mayúsculas).
ULID vs UUID
ULIDs y UUIDs ambos representan identificadores de 128 bits, pero difieren significativamente en codificación y objetivos de diseño:
| Propiedad | ULID | UUID |
|---|---|---|
| Formato | Crockford Base32 | Hexadecimal con guiones |
| Longitud | 26 caracteres | 36 caracteres |
| Marca de tiempo | Unix ms de 48 bits | Ninguno (v4) o ms de 48 bits (v7) |
| Ordenable | Sí — lexicográfico | No (v4) / Sí (v7) |
| Seguro para URL | Sí (solo alfanumérico) | Sí (con guiones) |
| Dependencias | Requiere biblioteca | Nativo (crypto.randomUUID) |
| Soporte BD | Almacenar como CHAR(26) o BINARY(16) | Tipo de columna UUID nativo |
| Especificación | Especificación comunitaria (ulid.github.io) | RFC 4122 / RFC 9562 |
Si ya está en un ecosistema UUID (columnas uuid de PostgreSQL, APIs REST, ORMs con soporte UUID), UUID v7 generalmente es una mejor opción que ULID. Si prefiere una codificación más amigable para humanos y controla la pila completa, ULID es una excelente elección.
ULID vs nanoid
Tanto ULID como nanoid producen identificadores cortos y seguros para URL, pero tienen diferentes objetivos de diseño:
| Propiedad | ULID | NanoID |
|---|---|---|
| Marca de tiempo | Sí — Unix ms de 48 bits | No |
| Ordenable | Sí | No |
| Longitud predeterminada | 26 caracteres | 21 caracteres |
| Entropía | 80 bits (componente aleatorio) | ~126 bits |
| Alfabeto | Crockford Base32 (32 caracteres) | Base64 seguro para URL (64 caracteres) |
| Longitud personalizable | No | Sí (cualquier longitud) |
| Caso de uso | IDs ordenados por tiempo, claves primarias BD | Tokens aleatorios, URLs cortas, claves API |
Elija ULID cuando necesite ordenación temporal. Elija nanoid cuando necesite máxima entropía en una cadena aleatoria corta.
Usando ULIDs en Bases de Datos
Los ULIDs pueden almacenarse en bases de datos de varias formas según sus requisitos:
Ejemplos de Código
La generación de ULID requiere la biblioteca ulid (disponible para JavaScript, Python, Go, Rust y más):
// Using the 'ulid' npm package
import { ulid } from 'ulid'
const id = ulid() // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
const id2 = ulid() // "01ARZ3NDEKXXXXXXXXXXXX..." (same ms, incremented random)
// With a custom timestamp
const id3 = ulid(1469918176385) // deterministic time portion
// Extract the timestamp back out
import { decodeTime } from 'ulid'
decodeTime(id) // → 1469918176385 (Unix ms)# Using python-ulid
from ulid import ULID
uid = ULID()
str(uid) # "01ARZ3NDEKTSV4RRFFQ69G5FAV"
uid.timestamp # 1469918176.385
uid.datetime # datetime(2016, 7, 30, 23, 36, 16, 385000, tzinfo=timezone.utc)
# Parse an existing ULID string
parsed = ULID.from_str("01ARZ3NDEKTSV4RRFFQ69G5FAV")
parsed.timestamp # 1469918176.385-- Store ULIDs as TEXT or CHAR(26)
CREATE TABLE events (
id CHAR(26) PRIMARY KEY DEFAULT gen_ulid(), -- if using a PG extension
name TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Or pass the ULID from your application layer
INSERT INTO events (id, name, created_at)
VALUES ('01ARZ3NDEKTSV4RRFFQ69G5FAV', 'user.signup', NOW());
-- Range queries are efficient because ULIDs sort chronologically
SELECT * FROM events
WHERE id > '01ARZ3NDEKTSV4RRFFQ69G5FAV'
ORDER BY id
LIMIT 20;// Pure browser / Deno / Node.js implementation (no dependencies)
const CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'
function encodeTime(ms) {
let result = '', n = BigInt(ms)
for (let i = 9; i >= 0; i--) {
result = CROCKFORD[Number(n & 31n)] + result
n >>= 5n
}
return result
}
function encodeRandom(bytes) {
let n = 0n
for (const b of bytes) n = (n << 8n) | BigInt(b)
let result = ''
for (let i = 15; i >= 0; i--) {
result = CROCKFORD[Number(n & 31n)] + result
n >>= 5n
}
return result
}
function generateULID() {
const randomBytes = new Uint8Array(10)
crypto.getRandomValues(randomBytes)
return encodeTime(Date.now()) + encodeRandom(randomBytes)
}