O que é um UUID?
Um UUID (Universally Unique Identifier, Identificador Universalmente Único), conhecido na terminologia da Microsoft como GUID (Globally Unique Identifier), é um número de 128 bits usado para identificar informações de forma única em sistemas computacionais. Ao contrário dos inteiros auto-incrementais que requerem uma autoridade central para atribuir o próximo valor, os UUID podem ser gerados independentemente por qualquer máquina, a qualquer momento, com uma probabilidade de colisão astronomicamente baixa.
A representação textual canônica de um UUID tem a seguinte aparência:
550e8400-e29b-41d4-a716-446655440000
^^^^^^^^ ^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^
tempo tempo ver. var. nó
Essa cadeia com hífens codifica 32 dígitos hexadecimais (128 bits) no formato xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx, onde:
- M é o dígito de versão (1, 3, 4, 5 ou 7)
- N é o nibble de variante (8, 9, a ou b para UUID conformes à RFC 4122)
Uma Breve História
O conceito de identificador universalmente único originou-se no final dos anos 1980 na Apollo Computer e na Digital Equipment Corporation (DEC) como parte do Sistema de Computação em Rede (NCS) e do Ambiente de Computação Distribuída (DCE). O objetivo era permitir que sistemas distribuídos criassem identificadores sem nenhum registro central.
A Microsoft adotou o conceito para COM/OLE e o chamou de GUID, mas a estrutura subjacente é idêntica a um UUID. Os dois termos são intercambiáveis na prática.
A especificação formal chegou com a RFC 4122, publicada em julho de 2005 pelo IETF. Ela padronizou cinco versões de UUID (v1–v5) e definiu os bits de variante. Duas décadas depois, a RFC 9562 (publicada em maio de 2024) substituiu a RFC 4122 e adicionou oficialmente UUID v6 e v7, que resolvem as deficiências de desempenho em banco de dados das versões anteriores.
Estrutura do UUID: 128 Bits Explicados
Um UUID sempre tem exatamente 128 bits (16 bytes). Formatado como string, tem 36 caracteres (32 dígitos hexadecimais + 4 hífens).
Campo Bits Dígitos hex Descrição
────────────────────────────────────────────────────────────────
time_low 32 8 32 bits baixos do timestamp (v1)
time_mid 16 4 16 bits médios do timestamp (v1)
time_hi_and_version 16 4 12 bits altos do timestamp + versão de 4 bits
clock_seq_hi_res 8 2 Bits de variante + sequência de clock alta
clock_seq_low 8 2 Sequência de clock baixa
node 48 12 ID do nó (endereço MAC em v1, aleatório nos outros)
A versão é codificada nos 4 bits mais significativos do campo time_hi_and_version (o 13.° caractere hexadecimal). A variante é codificada nos 2–3 bits mais significativos de clock_seq_hi_res (o 17.° caractere hexadecimal).
Versões do UUID Explicadas
Versão 1 — Baseada em Tempo
UUID v1 combina um timestamp de 60 bits (intervalos de 100 nanossegundos desde 15 de outubro de 1582) com o endereço MAC do host e uma sequência de clock.
Exemplo: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
Vantagens: Contém informações temporais, permitindo ordenação aproximada por hora de criação.
Desvantagens: Incorpora o endereço MAC, levantando preocupações de privacidade — pode revelar quando e onde um UUID foi gerado. Não recomendado para identificadores públicos.
Versão 2 — Segurança DCE
UUID v2 substitui parte do timestamp por um UID/GID POSIX e um identificador de domínio. É definido na especificação DCE 1.1, mas raramente usado na prática, pois sacrifica garantias de unicidade para incorporar o domínio.
Versão 3 — Baseada em Nome (MD5)
UUID v3 gera um UUID determinístico a partir de um UUID de namespace e um nome, fazendo hash deles com MD5.
Exemplo: 5df41881-3aed-3515-88a7-2f4a814cf09e (namespace DNS + "example.com")
Caso de uso: Identificadores estáveis e reproduzíveis para o mesmo recurso lógico. Se o mesmo namespace e nome forem hasheados duas vezes, sempre se obtém o mesmo UUID.
Atenção: MD5 é criptograficamente fraco. Prefira v5 para novos sistemas.
Versão 4 — Aleatória (A Mais Popular)
UUID v4 usa 122 bits de dados aleatórios criptograficamente seguros (os 6 bits restantes são usados para versão e variante).
Exemplo: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d
Esta é de longe a versão de UUID mais utilizada. Não requer coordenação, acesso à rede ou conhecimento do host. A aleatoriedade vem de um CSPRNG (gerador de números pseudo-aleatórios criptograficamente seguro).
Versão 5 — Baseada em Nome (SHA-1)
UUID v5 é conceitualmente idêntico ao v3, mas usa SHA-1 em vez de MD5.
Exemplo: 886313e1-3b8a-5372-9b90-0c9aee199e5d (namespace DNS + "example.com")
Caso de uso: Quando se precisa de UUID determinísticos e reproduzíveis e se quer um hash mais forte que MD5. SHA-1 não é criptograficamente seguro para todos os fins, mas sua resistência a colisões é significativamente melhor que a do MD5.
Versão 7 — Ordenada por Tempo (Recomendada para Bancos de Dados)
UUID v7 é a estrela da RFC 9562. Ela incorpora um timestamp Unix de 48 bits em milissegundos nos bits mais significativos, tornando o UUID k-ordenável: UUIDs gerados posteriormente se ordenam após UUIDs gerados anteriormente.
Exemplo: 018e8f5a-2b3c-7d4e-8f9a-0b1c2d3e4f50
Os primeiros 12 caracteres hexadecimais (018e8f5a-2b3c) codificam o timestamp em milissegundos. O restante é aleatório. Isso torna v7 ideal como chave primária de banco de dados: retém a unicidade global do v4, sendo ao mesmo tempo ordenada por inserção, o que reduz drasticamente a fragmentação do índice B-tree.
Probabilidade de Colisão: O Problema do Aniversário
UUID v4 usa 122 bits de aleatoriedade. A probabilidade de colisão pode ser estimada usando a fórmula do problema do aniversário:
p(n) ≈ 1 − e^(−n²/2N)
onde N = 2^122 ≈ 5,32 × 10^36 (total de UUIDs possíveis).
Para ter uma probabilidade de 50% de pelo menos uma colisão, seria necessário gerar aproximadamente 2,71 × 10^18 (2,71 quintilhões) de UUIDs. A uma taxa de 1 bilhão de UUIDs por segundo, isso levaria cerca de 86 anos.
Para fins práticos, as colisões de UUID v4 são tão improváveis que podem ser tratadas como impossíveis em qualquer aplicação do mundo real.
UUID vs. IDs Auto-Incrementais
| Característica | UUID v4 | Auto-Incremental |
|---|---|---|
| Escopo de unicidade | Global | Local (por tabela) |
| Local de geração | Lado do cliente | Lado do servidor |
| Previsibilidade | Não previsível | Sequencial |
| Segurança em URL | Sim (com codificação) | Sim |
| Desempenho índice BD | Ruim (aleatório) | Excelente (sequencial) |
| Fusão/replicação | Fácil | Propenso a conflitos |
| Tamanho de armazenamento | 16 bytes (binário) | 4–8 bytes |
| Legibilidade humana | Baixa | Alta |
| Segurança (enumeração) | Seguro | Vulnerável |
IDs auto-incrementais são perfeitamente adequados para aplicações de banco de dados único sem requisitos distribuídos. Os UUID se destacam quando:
- Múltiplos serviços ou bancos de dados precisam gerar IDs de forma independente.
- Registros podem ser mesclados de diferentes fontes.
- Se quer evitar expor IDs sequenciais em URLs (ataques de enumeração).
Desempenho em Banco de Dados: v4 vs. v7
O Problema com UUID v4 em Bancos de Dados
Como UUID v4 é aleatório, cada nova linha é inserida em uma posição aleatória no índice B-tree. Isso causa:
- Divisões de página de índice — o banco de dados precisa frequentemente dividir páginas de índice para acomodar inserções fora de ordem.
- Thrashing de cache — padrões de acesso aleatório anulam o pool de buffers, causando leituras frequentes do disco.
- Amplificação de escrita — significativamente mais E/S do que inserções sequenciais.
Benchmarks em tabelas grandes (>10 M de linhas) frequentemente mostram que chaves primárias UUID v4 têm desempenho 3–5 vezes pior do que chaves sequenciais para cargas de trabalho com muitas inserções.
UUID v7 Resolve Isso
UUID v7 é monotonicamente crescente dentro da mesma janela de milissegundo. Novos registros são inseridos no final ou próximo ao final do índice, semelhante ao auto-incremento. O resultado:
- Fragmentação de índice quase nula.
- Utilização ideal do pool de buffers.
- Desempenho de inserção comparável ao auto-incremento.
Recomendação: Use UUID v7 para qualquer novo esquema de banco de dados que precise de chaves primárias globalmente únicas.
Casos de Uso em Sistemas Distribuídos
UUIDs são a espinha dorsal da identidade distribuída:
- Microsserviços: Cada serviço pode gerar IDs de forma independente sem comunicar com um servidor de sequências central.
- Event sourcing: Eventos obtêm IDs imutáveis que permanecem únicos através de repetições e reidratações.
- CQRS: Comandos e consultas podem ser correlacionados por um UUID gerado no cliente.
- Bancos de dados multi-região: Registros criados em diferentes regiões nunca colidem, tornando triviais a consistência eventual e as operações de mesclagem.
- Chaves de idempotência: APIs podem usar UUIDs gerados pelo cliente como chaves de idempotência para repetir solicitações com segurança.
- Sistemas de conteúdo endereçável: UUID v3/v5 podem produzir identificadores estáveis para o mesmo recurso entre sistemas.
ULID: Uma Alternativa Moderna
ULID (Universally Unique Lexicographically Sortable Identifier) é uma alternativa ao UUID desenvolvida pela comunidade, que é segura para URLs por padrão e sempre ordenável.
| Característica | UUID v4 | UUID v7 | ULID |
|---|---|---|---|
| Ordenável | Não | Sim | Sim |
| Seguro para URL | Com codificação | Com codificação | Sim (Crockford Base32) |
| Componente temporal | Não | Sim (ms) | Sim (ms) |
| Padrão | RFC 9562 | RFC 9562 | Especificação comunitária |
| Comprimento do formato | 36 chars | 36 chars | 26 chars |
| Monotônico dentro do ms | Não | Opcional | Sim |
Um ULID parece 01ARZ3NDEKTSV4RRFFQ69G5FAV — 26 caracteres, sem hífens, seguro para usar diretamente em URLs. Se você precisa de ordenabilidade e segurança em URL sem se preocupar com compatibilidade RFC, o ULID vale a pena considerar.
Gerando UUID em Diferentes Linguagens
JavaScript / TypeScript (Node.js e Navegador)
import { v4 as uuidv4, v7 as uuidv7 } from 'uuid';
const randomId = uuidv4(); // "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
const sortableId = uuidv7(); // "018e8f5a-2b3c-7d4e-8f9a-0b1c2d3e4f50"
// crypto nativo (Node 14.17+ / navegadores modernos)
const nativeId = crypto.randomUUID(); // UUID v4
Python
import uuid
# v4 — aleatório
print(uuid.uuid4()) # "f47ac10b-58cc-4372-a567-0e02b2c3d479"
# v5 — determinístico de namespace + nome
print(uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com'))
# "886313e1-3b8a-5372-9b90-0c9aee199e5d"
Go
import "github.com/google/uuid"
id := uuid.New() // UUID v4
v7, _ := uuid.NewV7() // UUID v7 (google/uuid v1.6+)
fmt.Println(id.String())
Java
import java.util.UUID;
UUID v4 = UUID.randomUUID();
System.out.println(v4); // "3e4666bf-d5e5-4aa7-b8ce-cefe41c7568a"
Rust
use uuid::Uuid;
let v4 = Uuid::new_v4();
let v7 = Uuid::now_v7();
println!("{}", v4);
println!("{}", v7);
Melhores Práticas
- Use v4 para identificadores únicos de uso geral onde a ordenação não importa.
- Use v7 para chaves primárias de banco de dados para evitar fragmentação de índice e obter ordem de classificação natural.
- Use v5 para IDs determinísticos quando precisar que a mesma entrada sempre produza o mesmo UUID (ex.: desduplicação de conteúdo por URL).
- Evite v1 em contextos sensíveis à privacidade — ela incorpora seu endereço MAC e horário de criação.
- Armazene UUIDs como binário (16 bytes) no banco de dados, não como varchar(36), para economizar espaço e melhorar o desempenho do índice.
- Nunca use v2 a menos que esteja implementando especificamente DCE Security.
- Valide UUIDs de entrada nos limites da API para evitar injeção de identificadores malformados.
- Use uma biblioteca bem testada em vez de implementar sua própria geração de UUID — fontes de entropia são fáceis de implementar incorretamente.
Perguntas Frequentes
P: UUID e GUID são a mesma coisa?
R: Funcionalmente, sim. GUID é o nome da Microsoft para o mesmo formato de identificador de 128 bits. A estrutura é idêntica; apenas a terminologia difere.
P: Dois UUIDs podem ser iguais?
R: Em teoria sim, mas a probabilidade é negligenciável para v4. Seria necessário gerar 2,71 quintilhões de UUIDs para ter 50% de chance de uma única colisão. Na prática, você nunca encontrará uma colisão.
P: Qual versão de UUID devo usar para chaves primárias de banco de dados?
R: UUID v7 é a melhor escolha. É ordenado por tempo (bom para índices B-tree), globalmente único e padronizado na RFC 9562. Se sua biblioteca ainda não suporta v7, use um ULID ou um padrão "COMB" UUID como alternativa.
P: UUID v4 é seguro o suficiente para usar como token de sessão?
R: UUID v4 tem 122 bits de aleatoriedade, o que geralmente é suficiente. No entanto, bibliotecas dedicadas de tokens de sessão podem usar um pouco mais de entropia ou melhores codificações. Para contextos de alta segurança, prefira um gerador de tokens dedicado.
P: Como armazeno um UUID eficientemente em um banco de dados SQL?
R: Use um tipo de coluna UUID nativo se disponível (PostgreSQL, MySQL 8+), ou uma coluna BINARY(16). Evite CHAR(36) / VARCHAR(36), que ocupa 2,25 vezes mais espaço e é mais lento para indexar.
P: Qual é a diferença entre UUID v3 e v5?
R: Ambos são baseados em nome e determinísticos. v3 usa MD5; v5 usa SHA-1. SHA-1 tem melhor resistência a colisões, portanto v5 é preferido para novos sistemas. Nenhum deve ser usado para hashing crítico de segurança.
P: UUID v7 substitui UUID v4?
R: Para chaves primárias de banco de dados, sim — v7 é estritamente melhor. Para outros casos de uso (ex.: chaves de API, tokens, IDs de correlação) onde a ordenação é irrelevante, v4 ainda é perfeitamente adequado.
Resumo
UUIDs são uma primitiva fundamental na engenharia de software moderna. Entender as diferenças entre versões ajuda a fazer as escolhas corretas:
- v4 — melhor para unicidade geral sem coordenação.
- v5 — melhor para identificadores determinísticos e reproduzíveis.
- v7 — melhor para chaves primárias de banco de dados devido à ordenação temporal.
Seja construindo um monólito, uma arquitetura de microsserviços ou um banco de dados distribuído globalmente, os UUIDs fornecem uma maneira testada em batalha e padronizada de identificar seus dados de forma única e segura.