Gerador ULID

Gera identificadores únicos com ordenação lexicográfica

Quantidade

Clique em Gerar para criar ULIDs

O que é um ULID?

ULID (Identificador Universalmente Único Lexicograficamente Ordenável) é um formato de identificador de 128 bits projetado para ser tanto único quanto naturalmente ordenável. Ao contrário do UUID v4, que é totalmente aleatório, um ULID incorpora um timestamp Unix com precisão de milissegundos em seus bits mais significativos — garantindo que IDs gerados mais tarde sejam ordenados após IDs gerados antes.

ULIDs são codificados usando o alfabeto Crockford Base32, produzindo uma string compacta de 26 caracteres que é segura para URL, insensível a maiúsculas e livre de caracteres visualmente ambíguos.

A especificação ULID foi criada por Alizain Feerasta e é amplamente usada em sistemas distribuídos, event sourcing e chaves primárias de banco de dados onde tanto unicidade quanto ordenação temporal importam. ULIDs não são um padrão IETF — são uma especificação comunitária disponível em ulid.github.io.

Estrutura ULID

Um ULID tem 128 bits de largura, dividido em dois componentes:

TimestampAleatório
01ARZ3NDEKTSVE4RRFFQ69G5FAV
48 bits — timestamp Unix em milissegundos. Codifica o tempo de geração com precisão de 1 ms. Cobre datas até o ano 10889.80 bits — dados aleatórios criptograficamente seguros. Regenerados frescos para cada ULID (a menos que o modo de monotonicidade seja usado).

Codificado como 26 caracteres Crockford Base32: os primeiros 10 caracteres representam o timestamp, os últimos 16 representam o componente aleatório.

Alfabeto Crockford Base32

ULIDs usam a codificação Crockford Base32, que usa 32 dos 36 caracteres alfanuméricos. O alfabeto é: 0123456789ABCDEFGHJKMNPQRSTVWXYZ

Por que esses 32 caracteres?
0123456789ABCDEFGHJKMNPQRSTVWXYZ

Quatro caracteres são intencionalmente excluídos:

  • I e L são excluídos — facilmente confundidos com o dígito 1
  • O é excluído — facilmente confundido com o dígito 0
  • U é excluído — evita palavras obscenas acidentais nos IDs gerados
  • A codificação é insensível a maiúsculas01ARZ3NDEKTSV4RRFFQ69G5FAV e 01arz3ndektsv4rrffq69g5fav são o mesmo ULID

Crockford Base32 é mais eficiente que hexadecimal (32 símbolos vs 16) e mais legível para humanos que Base64 (sem caracteres + / =, insensível a maiúsculas).

ULID vs UUID

ULIDs e UUIDs ambos representam identificadores de 128 bits, mas diferem significativamente em codificação e objetivos de design:

PropriedadeULIDUUID
FormatoCrockford Base32Hexadecimal com hífens
Comprimento26 caracteres36 caracteres
TimestampUnix ms de 48 bitsNenhum (v4) ou ms de 48 bits (v7)
OrdenávelSim — lexicográficoNão (v4) / Sim (v7)
Seguro para URLSim (apenas alfanumérico)Sim (com hífens)
DependênciasRequer bibliotecaNativo (crypto.randomUUID)
Suporte BDArmazenar como CHAR(26) ou BINARY(16)Tipo de coluna UUID nativo
EspecificaçãoEspecificação comunitária (ulid.github.io)RFC 4122 / RFC 9562

Se você já está em um ecossistema UUID (colunas uuid do PostgreSQL, APIs REST, ORMs com suporte a UUID), UUID v7 geralmente é uma opção melhor que ULID. Se você prefere uma codificação mais amigável para humanos e controla toda a stack, ULID é uma excelente escolha.

ULID vs nanoid

Tanto ULID quanto nanoid produzem identificadores curtos e seguros para URL, mas têm objetivos de design diferentes:

PropriedadeULIDNanoID
TimestampSim — Unix ms de 48 bitsNão
OrdenávelSimNão
Comprimento padrão26 caracteres21 caracteres
Entropia80 bits (componente aleatório)~126 bits
AlfabetoCrockford Base32 (32 chars)Base64 seguro para URL (64 chars)
Comprimento personalizávelNãoSim (qualquer comprimento)
Caso de usoIDs ordenados por tempo, chaves primárias BDTokens aleatórios, URLs curtas, chaves API

Escolha ULID quando precisar de ordenação temporal. Escolha nanoid quando precisar de máxima entropia em uma string aleatória curta.

Usando ULIDs em Bancos de Dados

ULIDs podem ser armazenados em bancos de dados de várias formas dependendo de seus requisitos:

Armazenar como CHAR(26)
A abordagem mais simples. A ordem de classificação lexicográfica é preservada. Ligeiramente maior que o armazenamento binário, mas legível para humanos e fácil de depurar.
Armazenar como BINARY(16)
Decodifique o ULID para sua representação binária de 16 bytes para armazenamento compacto. Requer codificação/decodificação no código da aplicação. A ordem de classificação é preservada.
PostgreSQL
Armazene como CHAR(26) ou use o tipo bytea para armazenamento binário. Não há tipo ULID nativo, mas a ordenação lexicográfica em CHAR(26) funciona corretamente.
MySQL / MariaDB
Use CHAR(26) CHARACTER SET ascii para armazenamento eficiente. O armazenamento binário em BINARY(16) também funciona e economiza espaço.
SQLite
Armazene como TEXT. A comparação de texto padrão do SQLite ordena ULIDs corretamente devido ao seu design lexicográfico.
MongoDB
Armazene como um campo de string. A ordenabilidade lexicográfica do ULID funciona naturalmente com a comparação de strings do MongoDB.

Exemplos de Código

A geração de ULID requer a biblioteca ulid (disponível para JavaScript, Python, Go, Rust e mais):

JavaScript (ulid npm)
// 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)
Python (python-ulid)
# 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
PostgreSQL
-- 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;
JavaScript (pure — no dependencies)
// 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)
}

Perguntas Frequentes

ULIDs são globalmente únicos?
Sim — com muito alta probabilidade. O componente aleatório de 80 bits fornece 2^80 ≈ 1,2 × 10^24 valores possíveis por milissegundo por gerador. A probabilidade de uma colisão dentro do mesmo milissegundo entre diferentes geradores é insignificante para qualquer sistema prático. Para garantias rígidas de unicidade, use o modo monotônico, que incrementa o componente aleatório para IDs gerados dentro do mesmo milissegundo.
Um ULID é o mesmo que um UUID?
Não — ULIDs e UUIDs são codificações diferentes de um valor de 128 bits. Um ULID não pode ser diretamente substituído por um UUID em sistemas que validam o formato UUID (hexadecimal com hífens). No entanto, você pode converter entre representações ULID binário e UUID se necessário.
Como o modo monotônico do ULID funciona?
No modo padrão, o componente aleatório de 80 bits é gerado fresco para cada ULID. No modo monotônico, quando múltiplos ULIDs são gerados dentro do mesmo milissegundo, o componente aleatório do segundo e subsequentes IDs é o valor aleatório anterior mais um. Isso garante ordenação monotônica estrita dentro de um milissegundo em um único gerador.
Posso decodificar um ULID para obter o timestamp de geração?
Sim. Os primeiros 10 caracteres Crockford Base32 codificam o timestamp Unix de 48 bits em milissegundos. Decodifique esses caracteres usando o alfabeto Crockford Base32, interprete o resultado como um timestamp Unix em milissegundos e converta para uma data. Esta ferramenta faz exatamente isso.
ULID é um padrão oficial?
Não. ULID é uma especificação comunitária mantida em ulid.github.io. Não é um padrão IETF como UUID. Isso significa que não há um RFC oficial para referenciar, e as implementações podem variar ligeiramente. UUID v7 (RFC 9562, 2024) é a alternativa padronizada pela IETF com propriedades similares de ordenação temporal.