Todos os artigos
82 artigos · atualizado semanalmente Veja nossas Ferramentas
Todos os artigos
Tutoriais

O que é um UUID? Formato, versões e quando usar

UUID é um identificador de 128 bits sem coordenação central. Conheça o formato, as 8 versões (v1 a v8), NIL UUID, e quando usar cada versão em bancos e APIs.

COVER · Tutoriais

Em algum momento alguém te perguntou "qual ID você usa nas suas tabelas?" e a resposta ficou complicada. Auto-increment é simples mas vaza informação sobre volume. UUIDs são opacos mas parecem excessivos para quem nunca precisou coordenar inserções entre múltiplos serviços sem um banco central no caminho. A verdade é que UUID resolve um problema específico de forma elegante — e saber exatamente o que é, como está estruturado e quais versões existem faz diferença quando você precisa tomar essa decisão.

Este post cobre o formato e as versões. Para a comparação direta entre v4 e v7 — que é onde a maioria das dúvidas de produção aparece — o post UUID v4 vs UUID v7: qual usar no seu projeto? entra nos detalhes de performance e banco de dados.

O que é um UUID

UUID significa Universally Unique Identifier. É um número de 128 bits representado como 32 dígitos hexadecimais divididos em 5 grupos por hifens: 8-4-4-4-12. O resultado é algo assim:

550e8400-e29b-41d4-a716-446655440000

O que faz do UUID interessante não é o tamanho — é a propriedade de unicidade sem coordenação central. Você pode gerar um UUID em qualquer máquina, offline, sem consultar nenhum serviço, e a probabilidade de colisão com qualquer outro UUID já gerado no universo é astronomicamente pequena. Para v4 com 122 bits de aleatoriedade, você precisaria gerar aproximadamente 2,7 × 10¹⁸ UUIDs para ter 50% de chance de colisão. Isso nunca vai acontecer na prática.

Esse é o problema que UUID resolve: criar identificadores únicos em sistemas distribuídos onde múltiplos nós precisam gerar IDs sem se comunicar.

A anatomia dos 128 bits

A estrutura de um UUID não é só formatação visual. Os 128 bits têm campos específicos definidos pela RFC 4122 (atualizada pela RFC 9562 em 2024):

550e8400 - e29b - 41d4 - a716 - 446655440000
xxxxxxxx   xxxx   Mxxx   Nxxx   xxxxxxxxxxxx

O dígito M (bit 12–15 do terceiro grupo) indica a versão. No exemplo acima, 4 significa versão 4. O dígito N (bits 6–7 do quarto grupo) indica a variantea em hexadecimal é 1010 em binário, e os dois bits mais significativos 10 indicam a variante RFC 4122 (a padrão).

Essa estrutura é por que um parser consegue identificar a versão de um UUID só olhando para ele.

As versões de UUID

A especificação define 8 versões, cada uma com uma estratégia diferente de geração:

Versão 1 — Timestamp + endereço MAC Combina o timestamp atual (em intervalos de 100 nanossegundos desde 15 de outubro de 1582) com o endereço MAC da interface de rede. Tecnicamente ordenável, mas problemático por privacidade: o endereço MAC do servidor fica embutido em cada ID gerado. Raramente usado em sistemas novos.

Versão 2 — DCE Security Variante do v1 que substitui parte do timestamp por um identificador POSIX (UID ou GID). Praticamente nunca visto na prática fora de contextos DCE legados.

Versão 3 — Namespace + MD5 Determinístico: dado o mesmo namespace e o mesmo nome, sempre gera o mesmo UUID. Usa MD5 como função de hash. Útil para criar IDs estáveis para recursos identificados por nome, como URLs ou endereços de e-mail. MD5 não é mais considerado seguro para aplicações criptográficas, então v5 é preferível para casos novos.

Versão 4 — Aleatório 122 bits aleatórios, com os 6 bits restantes definindo versão e variante. É a versão mais usada hoje — praticamente o default em toda biblioteca e linguagem. Sem dependência de hardware ou estado externo; pura aleatoriedade de um CSPRNG.

Versão 5 — Namespace + SHA-1 Igual ao v3, mas usa SHA-1 em vez de MD5. Mais seguro que v3 e igualmente determinístico. Use v5 sempre que precisar de UUIDs derivados de um namespace e nome.

Versão 6 — Timestamp reordenado Reordenação dos campos do v1 para tornar o UUID ordenável lexicograficamente por tempo, mantendo compatibilidade com a estrutura gregoriana de timestamp do v1. Introduzido pela RFC 9562. Raro na prática — v7 substituiu o caso de uso com uma abordagem mais limpa.

Versão 7 — Timestamp Unix + aleatório 48 bits de timestamp Unix em milissegundos no início do UUID, seguidos de 74 bits aleatórios. Sortável cronologicamente, gerado de forma simples, sem dependência de endereço MAC. O sucessor moderno do v1 para chaves primárias. Definido pela RFC 9562 em 2024.

Versão 8 — Customizado Formato para implementações customizadas que não se encaixam nas versões anteriores. A RFC define apenas que os bits de versão e variante devem ser respeitados; o resto é da aplicação. Usado por projetos que precisam de propriedades específicas não cobertas pelas versões padrão.

O NIL UUID e o Max UUID

Dois valores especiais merecem menção:

O NIL UUID é 00000000-0000-0000-0000-000000000000 — todos os bits em zero. Equivale a um valor nulo ou sentinela. Usado em código para representar "ausência de UUID" de forma explícita, em vez de usar null.

O Max UUID é ffffffff-ffff-ffff-ffff-ffffffffffff — todos os bits em um. Introduzido pela RFC 9562 como o oposto do NIL, útil em comparações de range.

Como UUIDs são usados na prática

Chave primária de banco: o uso mais comum. UUID como PK elimina a necessidade de um sequenciador central, permite que diferentes serviços gerem IDs de forma independente e os merges de dados entre sistemas ficam sem conflito de ID. O custo é índices maiores e, dependendo da versão, fragmentação de B-tree (v4 é aleatório e fragmente; v7 é ordenado e não fragmenta — ver UUID v4 vs UUID v7).

ID de sessão e token de autenticação: UUID v4 como token temporário. O comprimento e a aleatoriedade são suficientes para a maioria dos casos, embora tokens de sessão de alta segurança às vezes usem mais bits ou formatos diferentes (como PASETO).

Idempotency key em APIs: quando um cliente faz uma requisição de pagamento e não sabe se ela chegou, reenviar com o mesmo UUID garante que o servidor processe apenas uma vez. O servidor armazena o UUID e retorna o resultado cacheado para requisições duplicadas.

Event IDs em event sourcing: cada evento recebe um UUID imutável que serve como identificador permanente no log. Com v7, os eventos ficam naturalmente ordenados por tempo de criação.

IDs em sistemas distribuídos e microserviços: dois serviços independentes podem gerar IDs sem risco de colisão. Sem UUID, você precisa de um gerador centralizado (que vira ponto único de falha) ou de particionamento de faixas de ID (que é manual e propenso a erro).

Suporte nativo por plataforma

// JavaScript (browser e Node.js 14.17+)
crypto.randomUUID(); // "b7a1c3d4-e5f6-4789-abcd-ef0123456789"
-- PostgreSQL
SELECT gen_random_uuid(); -- gera v4

-- MySQL 8.0+
SELECT UUID(); -- gera v1 (atenção: é v1, não v4)
# Python
import uuid
uuid.uuid4()  # versão 4
uuid.uuid5(uuid.NAMESPACE_URL, 'https://example.com')  # versão 5
// Go — biblioteca padrão não tem UUID; use github.com/google/uuid
id := uuid.New() // v4

Para gerar UUIDs v4 rapidamente no browser sem instalar nada, o Gerador de UUID cobre v4 e v7 com cópia direta para o clipboard.

UUID vs ULID vs NanoID

Três formatos frequentemente comparados:

ULID (Universally Unique Lexicographically Sortable Identifier): 128 bits como UUID v7, mas representado em Crockford Base32 (01H4P3KGQ1ABCDE...). Mais compacto textualmente, sortável. Não tem adoção como padrão oficial — é uma spec independente.

NanoID: string aleatória de comprimento configurável (default 21 caracteres), URL-safe. Mais curto que UUID para display, mas sem estrutura de versão ou timestamp. Bom para IDs em URLs, ruim para PKs de banco onde você quer sortability.

UUID: padrão internacional (RFC 9562), suporte nativo em bancos, linguagens e frameworks. Menos compacto visualmente, mas o mais interoperável. Para a maioria dos casos de banco de dados e APIs, UUID é a escolha óbvia.

Perguntas frequentes

UUID v4 pode colidir com outro UUID v4?

Teoricamente sim, na prática não. Com 122 bits de aleatoriedade, a probabilidade de gerar dois UUIDs idênticos é tão pequena que, para qualquer escala razoável de sistema, é efetivamente zero. Para ter 50% de chance de colisão, você precisaria gerar 2,7 × 10¹⁸ UUIDs. Para contexto: o mundo todo gera algo em torno de 10¹² UUIDs por ano.

UUID v1 ainda é seguro de usar?

Para novos sistemas, não vale a pena. O problema principal do v1 não é técnico — é que ele embute o endereço MAC do servidor no ID, o que expõe informação sobre a infraestrutura. Além disso, o timestamp do v1 usa uma escala não-padrão (100ns desde 1582). Para casos que precisam de UUIDs ordenáveis por tempo, v7 é a resposta correta.

Devo armazenar UUID como TEXT ou BINARY(16) no banco?

Depende do banco e do volume. Em PostgreSQL, o tipo nativo UUID (16 bytes) é mais eficiente que TEXT (37 bytes com hifens) para indexação e armazenamento. Em MySQL, não há tipo UUID nativo — BINARY(16) é mais eficiente que VARCHAR(36) para tabelas grandes, mas requer conversão manual. Para a maioria dos projetos com PostgreSQL, use o tipo UUID nativo e não se preocupe com isso.

UUID v7 já tem suporte em frameworks e ORMs?

Crescendo rapidamente. Hibernate suporta desde 6.2; TypeORM tem suporte experimental; Prisma ainda depende de extensões para geração server-side. No application level, bibliotecas como uuidv7 (npm) e github.com/gofrs/uuid (Go) já suportam. PostgreSQL 17 adicionou uuidv7() nativo. O ecosistema ainda está migrando, mas v7 é o caminho.

O que UUID realmente resolve

UUID é uma solução para um problema de coordenação. Quando você tem um único banco com um único sequenciador, auto-increment funciona bem. Quando você tem múltiplos serviços, múltiplas réplicas de banco, ou precisa gerar IDs offline antes de persistir, UUID elimina a dependência de um ponto central.

A escolha de versão importa mais do que parece: v4 é simples e onipresente, mas fragmenta índices em escala. v7 é ordenado e resolve esse problema ao custo de uma biblioteca adicional hoje (e sem custo nenhum amanhã, quando o suporte nativo for ubíquo). Para novos projetos com tabelas que vão crescer, v7 é a decisão certa.

RD
Autor
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
Ver perfil