1001Ferramentas
🆔Validadores

Validador de ULID

Valida ULIDs (Universally Unique Lexicographically Sortable Identifier) — 26 caracteres do alfabeto Crockford Base32.

Validação de ULID: identificador ordenável sem a dor do UUID v4

Um ULID (Universally Unique Lexicographically Sortable Identifier) é um identificador de 128 bits proposto por Alizain Feerasta em 2016 como alternativa pragmática ao UUID v4. O spec define uma forma fixa em string de 26 caracteres em Crockford Base32, codificando um timestamp Unix em milissegundos de 48 bits seguido por 80 bits de aleatoriedade — um exemplo real é 01H7XBJX2VJF8Z5TQXM9RTPDC0.

O truque está no alfabeto Crockford: ele exclui de propósito as letras visualmente ambíguas I, L, O e U, então um ULID pode ser ditado por telefone, impresso em um cupom ou lido por OCR sem ambiguidade. A validação estrutural se reduz a uma regex case-insensitive:

/^[0-9A-HJKMNP-TV-Z]{26}$/i

Anatomia dos 26 caracteres

  • Caracteres 1–10 — timestamp de 48 bits, milissegundos desde a epoch Unix. Suficiente até o ano 10889.
  • Caracteres 11–26 — 80 bits de aleatoriedade criptográfica. São 1,21 × 10²⁴ valores distintos por milissegundo.
  • Como o timestamp vem primeiro e o alfabeto é ordenado, a ordenação lexicográfica coincide com a cronológica. ORDER BY id equivale a ORDER BY created_at — sem coluna extra.
  • O spec também define um modo monotônico: se dois ULIDs forem gerados no mesmo milissegundo, a parte aleatória do segundo é incrementada a partir do primeiro, garantindo ordem estrita sem colisão.

ULID vs UUID v4 vs UUID v7

ULID vs UUID v4: v4 são 122 bits de aleatoriedade pura — não ordenável, o que causa fragmentação de índice B-tree em Postgres e MySQL. O ULID resolve isso colocando o tempo primeiro. ULID também é mais curto como string (26 vs 36 caracteres) e sem hífens.

ULID vs UUID v7 (RFC 9562, 2024): ambos codificam timestamp em milissegundos + aleatoriedade em 128 bits, mas v7 agora é padrão IETF e o ULID continua sendo spec de comunidade. O UUID v7 reutiliza a forma hex 8-4-4-4-12 (36 caracteres); o ULID usa Crockford Base32 (26 caracteres, sem letras ambíguas). Para projetos novos em greenfield, UUID v7 é a escolha mais segura por interoperabilidade; ULID continua popular quando a string menor e o alfabeto humano importam.

Armazenamento, bibliotecas e pegadinhas

No Postgres normalmente se armazena ULID como CHAR(26) ou VARCHAR(26), às vezes como BYTEA(16) para compactação. Bibliotecas de validação na natureza: ulid no npm (de Eric Vallabh Minikel), python-ulid, ulid-rs em Rust. A caixa padrão é maiúscula, mas a maioria dos parsers aceita minúscula também — comparação case-insensitive é o mais seguro. A maior pegadinha operacional é o clock drift: se o relógio de um servidor pular para trás, ULIDs novos vão ordenar antes de antigos, quebrando a garantia de ordem por tempo. Mantenha o NTP saudável.

Onde o ULID brilha

  • Chaves primárias distribuídas — gerar IDs em qualquer nó sem coordenação, mantendo inserts amigáveis ao índice. No Brasil, times como Nubank e RD Station já usam ULID em algumas tabelas onde UUID v4 dava fragmentação.
  • Event sourcing — eventos ordenam naturalmente por tempo, sem sequência separada.
  • IDs de correlação de log — fáceis de copiar e colar no terminal, sem caracteres ambíguos.
  • Chaves IndexedDB — travessia ordenada de cursor no navegador.

Perguntas frequentes

ULID deve substituir UUID em projeto novo? Sim se você indexa por ID e precisa de ordenação temporal, e seu stack já tem uma lib de ULID. Caso contrário, use UUID v7 — ele dá a mesma ordenação com formato padronizado.

ULID é case-sensitive? Não. A saída canônica é maiúscula, mas Crockford Base32 é case-insensitive na entrada; 01h7xbjx2vjf8z5tqxm9rtpdc0 decodifica para os mesmos bytes da forma em maiúscula.

Qual o risco de colisão? 80 bits de aleatoriedade por milissegundo. Para chegar a 50% de probabilidade de colisão no mesmo milissegundo pelo limite do paradoxo do aniversário, seriam necessários cerca de 1,2 bilhão de ULIDs naquele milissegundo — praticamente impossível. Entre milissegundos, o prefixo de timestamp garante unicidade.

O timestamp vaza informação? Sim — qualquer um que leia um ULID consegue decodificar o milissegundo de criação. Se você publica IDs para usuários não confiáveis e precisa de privacidade do instante de criação, prefira UUID v4 ou faça hash do ULID.

Ferramentas Relacionadas