Pular para conteúdo

Fase 3 — UUID v7 (PostgreSQL 18+)

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-15 · Decidido em: 2026-07-06

Objetivo: migrar identificadores de UUID v4 (gen_random_uuid() no id) para UUID v7 (ordenável no tempo, RFC 9562), com baixo risco e janelas de migração controladas.

Por que esta ordem (recomendada)

  1. Flyway (este repositório) adiciona id_v7 UUID nullable em todas as tabelas com PK id UUID, sem alterar id, PKs nem FKs.
  2. Job / ferramenta banco → banco (fora deste JAR) preenche id_v7 com a estratégia de negócio (ex.: derivar timestamp de colunas existentes, mapeamento 1:1 do id antigo para um v7 gerado de forma reproduzível, etc.).
  3. Migração Flyway V15 (passo 3): após dados estáveis e backfill, renomear a coluna id (v4) para old_id (deixa de ser PK; mantém índice idx_*_old_id), renomear id_v7 → id (nova PK com DEFAULT uuidv7()). O UUID legado permanece consultável em old_id (ex.: PowerSync resolve por id ou old_id).
  4. Migração Flyway V16 (passo 4): a V15 deixa old_id NOT NULL (herdado da antiga PK); a V16 faz ALTER COLUMN old_id DROP NOT NULL nas tabelas de domínio, para permitir novos inserts apenas com id v7 (sem UUID legado em old_id).

Assim o schema permanece válido entre os passos; rollback é mais simples (colunas extras vs. troca de PK no meio do caminho).

Escopo das tabelas (id UUID)

Tabela Notas
contratos, estoque, itens, itenslote, itensped, itenspedamx, itpedamxdi, loteest, municipio, notacompl, propriedades, tbpcoest, veiculos PK id UUID desde V1+

Fora deste passo: request e push_enviada usam BIGINT identity; pabast_* usam VARCHAR como PK — não recebem id_v7 nesta fase.

Migração Flyway

  • V14__uuid_v7_add_id_v7_columns.sql (em db/migration): ALTER TABLE ... ADD COLUMN IF NOT EXISTS id_v7 UUID + comentários.
  • V15__uuid_v7_id_old_id_swap.sql (em db/migration): troca de PK conforme acima; cópia de referência em docs/dev/sql/V15__uuid_v7_swap_id_rename_to_id.sql.
  • V16__old_id_nullable.sql (em db/migration): old_id passa a aceitar NULL; cópia em docs/dev/sql/V16__old_id_nullable.sql.

Ordem operacional e deploy: runbook-migration-uuid-v7.md.

Não define DEFAULT uuidv7() na V14: enquanto o backfill não estiver completo, defaults automáticos poderiam gerar v7 “novos” por linha de forma indesejada; a V15 fixa DEFAULT uuidv7() após o rename.

Runbook (operacional)

Passo a passo: backup, V14, sincronização de dados, V15, deploy — runbook-migration-uuid-v7.md.

PostgreSQL 18 e uuidv7()

A função uuidv7() está disponível no PostgreSQL 18+. Use essa versão (ou superior) no servidor e nos testes de integração que validam uuidv7().

Migrações que apenas adicionam coluna UUID sem chamar uuidv7() no SQL rodam em versões anteriores; qualquer migration futura que use uuidv7() no DDL exige PG 18+.

Testes

O projeto inclui teste de integração com Testcontainers (postgres:18) que aplica todo o histórico Flyway e verifica:

  • com Flyway até V14: presença de id_v7 nas tabelas listadas; com histórico completo (V15–V16): colunas id e old_id em tabelas de domínio, sem id_v7, e old_id anulável (V16);
  • SELECT uuidv7() executa com sucesso.

Requisito: Docker disponível na máquina / CI ao rodar esses testes.

Para ignorar o teste Testcontainers (ex.: ambiente sem daemon Docker): variável de ambiente SKIP_DOCKER_TESTS=true.

Correção 2026-09-15: o SKIP_DOCKER_TESTS não é lido por nenhum teste. O teste da linha do tempo de migration (Postgres18UuidV7FlywayIntegrationTest) sobe um container dedicado e leva o @IntegracaoDocker da xadm-comum-teste: roda por padrão e só pula com o Docker ausente, com o motivo em ERROR no log e no relatório do JUnit (micronaut-profiles).

Referências