← Início / Artigos Técnicos / UUID v4 vs UUID v7
Bancos de Dados & RFC 9562

UUID v4 vs UUID v7: Por Que o Novo Padrão Revolucionou Bancos de Dados

Por Equipe Técnica Caixa do Dev • Tempo de leitura: 8 minutos • Atualizado em Outubro de 2026

Por quase duas décadas, engenheiros de software enfrentaram um clássico dilema ao modelar chaves primárias (PKs) em bancos de dados relacionais como PostgreSQL, MySQL e MariaDB: usar inteiros sequenciais auto-incrementais (BIGINT) ou identificadores universais aleatórios (UUID v4)?

Apesar de o UUID v4 oferecer vantagens inestimáveis para sistemas distribuídos e microsserviços — como geração sem colisão descentralizada e impossibilidade de enumeração de dados por atacantes via URL —, sua total aleatoriedade cobra um preço catastrófico em escala: a fragmentação descontrolada de páginas em árvores B-Tree.

Em maio de 2024, a IETF oficializou a RFC 9562 (que substituiu a histórica RFC 4122), padronizando novas versões de UUIDs. Entre elas, o UUID v7 tornou-se a escolha definitiva para arquiteturas modernas de alta vazão.

1. O Problema Oculto do UUID v4: Fragmentação de Índices B-Tree

Bancos de dados relacionais organizam suas chaves primárias e índices em estruturas de árvore balanceada chamadas B-Trees. Quando você insere dados sequenciais (como um ID 1, 2, 3...), o banco de dados simplesmente anexa novos registros no final da última página de disco da árvore, mantendo as páginas anteriores intocadas e o cache da memória RAM altamente eficiente.

Entretanto, como o UUID v4 possui 122 bits de pura aleatoriedade criptográfica, cada nova inserção atinge uma posição completamente arbitrária da árvore:

Os 3 Sintomas da Degradação por UUID v4 em Tabelas com Milhões de Linhas:

  • Page Splits (Divisões de Página): Quando uma página de 8 KB está cheia e recebe um novo registro no meio dela, o banco precisa dividi-la em duas páginas semicheias, reescrevendo blocos no disco.
  • Buffer Cache Thrashing: Como as inserções são em posições aleatórias, o banco precisa carregar constantemente páginas antigas do disco para a memória RAM, expulsando dados úteis de cache.
  • Bloat de Índice: Índices em UUID v4 costumam ocupar de 30% a 50% mais espaço em disco do que o necessário devido às páginas deixadas parcialmente vazias após divisões.

2. A Anatomia do UUID v7 (RFC 9562)

O UUID v7 resolve esse gargalo combinando o melhor dos dois mundos: ordenação temporal monotônica na raiz com alta entropia aleatória nas pontas. Ele continua tendo exatamente os mesmos 128 bits (16 bytes) e a mesma representação textual de 36 caracteres do padrão UUID:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           unix_ts_ms                          | (32 bits)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          unix_ts_ms           |  ver  |       rand_a          | (16 + 4 + 12 bits)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var|                        rand_b                             | (2 + 62 bits)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        

A estrutura divide-se em três seções críticas:

  1. unix_ts_ms (48 bits): Armazena o timestamp Unix atual em milissegundos. Permite ordenação cronológica precisa até aproximadamente o ano 10.889.
  2. version (4 bits): Valor fixo 0111 em binário (versão 7).
  3. rand_a + rand_b (74 bits de entropia): Garante que centenas de milhares de UUIDs gerados no exato mesmo milissegundo nunca colidam entre si.

3. Comparativo de Performance: UUID v4 vs UUID v7

Característica UUID v4 UUID v7
Ordenação Natural Não (100% caótico) Sim (Ordenado por timestamp)
Desempenho em B-Tree Queda de até 75% em 50M+ linhas Quase idêntico a BIGINT sequencial
Fragmentação de Páginas Alta (constantes page splits) Mínima (append nas folhas finais)
Privacidade de Enumeração Total (impossível adivinhar IDs) Total (74 bits de entropia aleatória)
Vazamento de Timestamp Nenhum Expõe o milissegundo de criação

4. Implementação Prática: Como Gerar UUID v7

Em JavaScript (Node.js nativo com Web Crypto API)

function gerarUUIDv7() {
  const bytes = new Uint8Array(16);
  crypto.getRandomValues(bytes);

  const timestamp = Date.now();

  // Escreve os 48 bits de timestamp Unix (Big Endian)
  bytes[0] = (timestamp / 0x10000000000) & 0xff;
  bytes[1] = (timestamp / 0x100000000) & 0xff;
  bytes[2] = (timestamp / 0x1000000) & 0xff;
  bytes[3] = (timestamp / 0x10000) & 0xff;
  bytes[4] = (timestamp / 0x100) & 0xff;
  bytes[5] = timestamp & 0xff;

  // Ajusta a versão (0111 = 7) nos 4 bits superiores do byte 6
  bytes[6] = (bytes[6] & 0x0f) | 0x70;

  // Ajusta a variante RFC 4122/9562 (10xx) nos 2 bits superiores do byte 8
  bytes[8] = (bytes[8] & 0x3f) | 0x80;

  // Converte para a string hexadecimal formatada com hífens
  return [...bytes].map((b, i) => {
    const hex = b.toString(16).padStart(2, '0');
    return (i === 4 || i === 6 || i === 8 || i === 10) ? '-' + hex : hex;
  }).join('');
}

console.log(gerarUUIDv7());
// Exemplo: 018e6973-7721-72f1-9cb6-17b5e4070a84
        

Em Python 3

import time
import os
import uuid

def gerar_uuid_v7() -> uuid.UUID:
    unix_ts_ms = int(time.time() * 1000)
    rand_bytes = bytearray(os.urandom(10))

    # Converte timestamp em 6 bytes
    ts_bytes = unix_ts_ms.to_bytes(6, byteorder='big')
    raw = bytearray(ts_bytes + rand_bytes)

    # Configura versão 7
    raw[6] = (raw[6] & 0x0F) | 0x70
    # Configura variante RFC 9562 (10xx xxxx)
    raw[8] = (raw[8] & 0x3F) | 0x80

    return uuid.UUID(bytes=bytes(raw))

print(gerar_uuid_v7())
        

Perguntas Frequentes (FAQ)

O PostgreSQL já suporta UUID v7 nativamente?+
O tipo de dados nativo UUID do PostgreSQL armazena 128 bits e funciona perfeitamente com UUID v7. Na versão 17, foram introduzidas discussões avançadas de funções de geração embutidas, mas até lá qualquer biblioteca de backend (como TypeORM, Prisma, SQLAlchemy) pode gerar o UUID v7 no momento da inserção.
UUID v7 substitui o ULID?+
Sim. O ULID foi criado pela comunidade para suprir exatamente essa deficiência do UUID v4 antes da padronização oficial da IETF. Com a publicação da RFC 9562, o UUID v7 é o padrão oficial universal aceito nativamente por todos os bancos sem exigir codificações especiais em Base32.
Existe risco de expor o horário de criação do registro no ID?+
Se o momento exato em que um usuário ou recurso foi criado for um segredo comercial absoluto, o UUID v7 expõe esse milissegundo nos primeiros 48 bits. Para 99% das aplicações empresariais e públicas, no entanto, isso não é uma vulnerabilidade de segurança.
CD

Editorial Técnico Caixa do Dev

Artigos originais e guias técnicos produzidos com rigor matemático, código aberto e conformidade com especificações da IETF (RFCs), W3C e ISO/IEC para desenvolvedores.

Testar no Gerador de UUID (v4) → ← Ver Todos os Artigos