UUIDs resolvem um problema que ninguém pensa muito: como dois sistemas, que nunca se falaram, concordam em identificadores únicos sem coordenação central? Mas nem todo UUID serve pra qualquer trabalho — escolher a versão errada pode degradar a performance do seu banco em uma ordem de grandeza. Este é o guia honesto.
As versões de UUID
Um UUID tem 128 bits — 16 bytes — escritos como 32 caracteres hexadecimais minúsculos divididos em grupos 8-4-4-4-12. Dentro desse formato fixo, a RFC 9562 (a especificação de maio de 2024 que substituiu a antiga RFC 4122) define oito famílias que se distinguem por como os bits são preenchidos.
- v1 — timestamp + nó. A original. Combina 60 bits de timestamp com 48 bits de identificador de nó. Historicamente esse nó era o endereço MAC da máquina, o que vazava identidade de hardware em todo registro emitido. A RFC 4122 §4.5 permite usar um nó aleatório com o bit multicast setado — caminho que nosso gerador adota. Nunca lemos o seu MAC.
- v3 e v5 — baseados em nome. Hashes determinísticos de um namespace mais um nome (v3 com MD5, v5 com SHA-1). A mesma entrada sempre gera o mesmo UUID. Útil quando você precisa de um identificador estável a partir de uma string estável.
- v4 — aleatório. 122 bits de aleatoriedade criptográfica com as posições de versão e variante fixas. É o que a maioria das pessoas quer dizer com "UUID". Excelente em propriedade de colisão, péssimo em performance de inserção em índice B-tree.
- v6 — v1 reordenado. Mesmos campos do v1, mas com a parte do timestamp reorganizada em ordem big-endian, o que torna o resultado ordenável. Pouco comum na prática; o v7 é o sucessor reconhecido.
- v7 — tempo Unix + aleatório. 48 bits de timestamp Unix em milissegundos no início, seguidos por 74 bits aleatórios. A ordem lexicográfica coincide com a ordem de inserção. O novo padrão de fato pra chaves primárias.
- v8 — customizado. Reservado pra layouts específicos de aplicação; não geramos.
Quando usar v4 e quando usar v7
A decisão quase sempre se resume a uma pergunta: o identificador vai ser chave primária em algum banco relacional?
Escolha v4 quando: o UUID vai identificar tokens de API, chaves de idempotência, sessões, envelopes de mensagem, eventos distribuídos, ou qualquer coisa que viva em um armazenamento com estrutura tipo hash. A distribuição aleatória é exatamente o que essas estruturas esperam.
Escolha v7 quando: o UUID vai virar chave de clustering num índice B-tree — PostgreSQL, MySQL InnoDB, SQL Server. Identificadores k-ordenáveis transformam inserções em appends, que é exatamente o padrão de acesso que B-trees foram desenhadas pra absorver.
A vantagem k-ordenável do v7
Um índice B-tree mantém suas folhas ordenadas pela chave. Quando você insere um UUID v4, o motor precisa achar a folha certa em uma posição aleatória da árvore — e frequentemente precisa dividir essa folha porque não cabe mais nada. Divisões de página escrevem o dobro de páginas, fragmentam o índice e arruínam a localidade de cache no padrão "lê o que acabou de escrever".
Um UUID v7 é monotônico dentro da resolução de um milissegundo. Inserções novas quase sempre caem na mesma folha mais à direita da anterior. Sem divisão de página, sem fragmentação, sem cache miss.
Benchmarks independentes em PostgreSQL — publicados em 2024 e 2025 — quantificam a diferença: inserir 50 milhões de linhas com v4 levou aproximadamente 20 minutos, contra 1 minuto e 46 segundos com v7. O índice gerado pelo v4 ficou 24% maior e o rebuild completo demorou onze vezes mais. A densidade de folha caiu pra 71% no v4 contra 89,98% no v7. O PostgreSQL 18, lançado em 2025, embarcou uma função nativa uuidv7() em parte por causa desses números. Pra quem opera bancos de alta ingestão — e fintechs e marketplaces brasileiros são particularmente expostas a esse padrão de carga —, a diferença é financeira, não estética.
A anatomia de um UUID
Os cinco segmentos da forma canônica não são arbitrários. Cada um carrega bits diferentes dependendo da versão:
xxxxxxxx - xxxx - Mxxx - Nxxx - xxxxxxxxxxxx
|------| |--| |--| |--| |---------|
seg 1 seg 2 seg 3 seg 4 seg 5
8 hex 4 hex 4 hex 4 hex 12 hex
^
| M = nibble de versão (1, 4, 7…)
^
| N = bits altos da variante
| 8/9/a/b = variante RFCNo v4, os segmentos 1–2–5 e a cauda dos segmentos 3–4 carregam só aleatoriedade. No v1, o segmento 1 é time_low, o 2 é time_mid, o 3 carrega o nibble de versão e os 12 bits altos do timestamp, o 4 segura a variante e uma sequência de relógio de 14 bits, e o 5 é o nó de 48 bits. No v7, os segmentos 1–2 são os 32 + 16 = 48 bits mais significativos do timestamp Unix em milissegundos; o 3 empacota o nibble de versão com os primeiros 12 bits de aleatoriedade; o 4 segura a variante e o topo do campo aleatório de 62 bits; o 5 é o resto desse campo.
Probabilidade de colisão
Um UUID v4 carrega 122 bits aleatórios — algo como 5,3 × 1036 valores distintos. O limite do paradoxo do aniversário diz que você precisaria gerar aproximadamente 2,71 × 1018 UUIDs antes que a probabilidade de colisão chegue em 50%. Em termos práticos: gerando um bilhão de UUIDs v4 por segundo, você atinge esse marco depois de 86 anos. Pra qualquer decisão de engenharia, isso é a definição de "seguro".
O v7 tem menos bits aleatórios por identificador (74 em vez de 122), mas o prefixo do timestamp particiona o espaço — dois UUIDs v7 só colidem se compartilharem o milissegundo E colidirem nos 74 bits da cauda. A margem prática de segurança é a mesma.
Quando NÃO usar UUIDs
- URLs públicas. Um identificador de 36 caracteres na barra de endereço é feio e desestimula compartilhamento. Considere
nanoid(21 caracteres URL-safe) ou um slug derivado do conteúdo. - Referências legíveis por humanos. "Pedido #12847" funciona melhor que "Pedido 550e8400-e29b-41d4-a716-446655440000" no atendimento. Chaves de auto-incremento ainda têm seu espaço, especialmente em referência de NF-e e atendimento ao cliente.
- Chaves compostas em índices densos. 16 bytes pesam quando você tem 600 milhões de linhas e quer manter o índice inteiro no shared buffer. Alternativas compactas (Snowflake IDs de 8 bytes, por exemplo) podem compensar o custo de coordenação.
- Identificadores "anônimos" que não são. Se você inadvertidamente embute informação que permite enumerar usuários, a aleatoriedade do UUID não te salva de nada. Aleatório não é sinônimo de privado — algo que a LGPD não distingue: o critério é o dado ser identificável, não o formato em que está.

