Parte 2: O novo playbook da Jen
por Pramod Sadalage e Kevin Hartman
Esta série revisita a metodologia de Design de Banco de Dados Evolucionário (Evolutionary Database Design), vinte anos depois. Uma limitação fundamental para mudanças de banco de dados como código sempre esteve relacionada a recursos compartilhados de banco de dados. Com a ramificação copy-on-write no Databricks Lakebase, criar uma ramificação (branch) de um segundo e com zero armazenamento na criação de um banco de dados de produção em escala de terabytes agora é uma operação O(1), e a limitação que mantinha a Prática nº 4 (cada um tem sua própria instância de banco de dados) no campo das aspirações foi superada. Nesta série, os autores descrevem o que muda quando essa limitação deixa de existir: não a metodologia, que se mantém, mas as práticas que surgem pela primeira vez, a governança em escala de equipe que se torna automática, a evolução do papel do DBA e a nova capacidade que os agentes compartilham com seus equivalentes humanos.
Jen é a personagem desenvolvedora de Evolutionary Database Design. Naquele artigo, ela implementou uma refatoração de banco de dados, dividindo um campo inventory_code em location_code, batch_number e serial_number, como uma história de usuário rotineira, ilustrando que DBAs e desenvolvedores podem colaborar, os esquemas podem evoluir em pequenos incrementos e as migrações levam a alteração adiante com segurança.
A série continua com Jen vinte anos depois. A metodologia que ela segue é a mesma de 2003. A novidade é a capacidade técnica por trás de seu fluxo de trabalho, viabilizada pela arquitetura lakebase: ramificação de banco de dados copy-on-write, que torna as práticas sobre as quais ela leu operacionalmente reais em escala de produção. Ao longo das três partes desta série, ela é a mesma Jen em três escopos: seu dia a dia (Parte 1), seu novo manual de táticas (Parte 2) e sua equipe (Parte 3).
A Parte 1 guiou Jen por uma funcionalidade. As práticas que ela seguiu foram descritas no artigo de 2003 Evolutionary Database Design, expandidas no livro de 2006 Refactoring Databases e integradas ao pipeline de CI/CD no livro de 2010 Continuous Delivery (Capítulo 12).
O artigo de 2003 nomeou sete práticas. Cinco das sete apresentavam limitações em sua aplicação até 2026.
A tecnologia introduzida pelo Databricks Lakebase remove os obstáculos para a implementação das práticas acima. O Databricks Lakebase é um banco de dados Postgres gerenciado que usa a mesma camada de armazenamento de objetos (o data lake) na qual o restante do lakehouse da Databricks é executado. Os dados do banco de dados residem em um armazenamento durável e compartilhado – efetivamente buckets do S3; o mecanismo Postgres é executado como uma camada de computação separada acima dele. Computação e armazenamento escalam de forma independente. O mecanismo pode escalar verticalmente sob carga, reduzir quando o tráfego cai e ir a zero quando inativo. O Lakebase é integrado ao Unity Catalog, permitindo uma governança unificada em múltiplos ambientes.
A ramificação de banco de dados copy-on-write é o que a arquitetura desacoplada torna viável em escala. Uma ramificação (branch) cria um novo ponteiro para o mesmo armazenamento compartilhado com um marcador de divergência. Até que a ramificação grave dados, ela compartilha todas as páginas com seu elemento pai. Quando a ramificação grava dados, apenas as páginas modificadas divergem; o elemento pai permanece inalterado. A ramificação é uma operação de metadados, sem necessidade de cópia de dados, sendo concluída em cerca de um segundo, independentemente do tamanho do elemento pai. As ramificações mantêm os dados apenas nas páginas alteradas.
Quando o custo técnico de uma ramificação é desacoplado do tamanho dos dados contidos nela, a limitação por trás da Prática nº 4 (cada um tem sua própria instância de banco de dados) é desbloqueada. Ramificações por desenvolvedor, por PR e por experimento tornam-se rotina. A camada de compensação acima pode ser removida. Os mocks saem do ciclo de teste, substituídos por um Postgres real em uma ramificação por teste. O ambiente de staging compartilhado deixa de ser o único lugar para testar alterações de esquema. Substitutos de banco de dados em memória (H2, SQLite) saem da camada de teste de unidade. O esforço de DevOps para criar contêineres baseados em Docker para executar bancos de dados locais não é mais necessário, e as filas de chamados de DBA para provisionamento diminuem porque as ramificações são de autoatendimento.
A tecnologia é o que viabiliza as otimizações de metodologia e concretiza o objetivo das práticas por trás da publicação original de 2003.
A ramificação de banco de dados copy-on-write do Lakebase supera as limitações anteriores das práticas originais e viabiliza quatro práticas adicionais para detalhamento.
As duas práticas que mais melhoram devido à capacidade fornecida pelo Lakebase são a nº 4 (todos têm sua própria instância de banco de dados) e a nº 5 (os desenvolvedores integram continuamente as alterações de banco de dados). Agora, não apenas todos têm um banco de dados, mas cada PR ou cada branch, ou múltiplos bancos de dados por branch, podem ser obtidos com custo e tempo insignificantes. O mecanismo pode ser automatizado usando dois templates de fluxo de trabalho do GitHub Actions que podem ser estruturados em cada projeto.
Criação de branch por PR. pr.yml é acionado em pull_request: [opened, synchronize] e cria ci-pr-<N> bifurcado a partir da branch base do PR:
O mesmo job aplica migrações na branch de CI e executa a suíte de testes da aplicação em um banco Postgres real. O exemplo completo do fluxo de trabalho pode ser encontrado aqui: pr.yml
Diff de esquema publicado no PR. O mesmo job pr.yml extrai o esquema de ambas as branches, formata o diff e o publica como um comentário no PR. É isso que permite ao DBA fazer a revisão de forma assíncrona, como qualquer revisor de código (Prática nº 1, reformulada):
O DBA, o revisor de código, a equipe e qualquer agente autor da migração visualizam o mesmo artefato no PR.
Limpeza de branch no merge. merge.yml destrói a branch de Pull Request de CI ci-pr-<N> e a branch do Lakebase vinculada à feature branch no momento em que o PR é mesclado:
O exemplo completo do fluxo de trabalho de merge pode ser encontrado aqui: merge.yml Com tantas branches ativas, pode valer a pena ter um script de limpeza semanal que remova branches órfãs e não utilizadas. Um exemplo de fluxo de trabalho pode ser encontrado aqui: cleanup-orphans.yml. Por fim, se o merge for em uma branch "em camadas" (tiered), por exemplo, usada para staging ou main/produção (este conceito será detalhado na parte 3), o fluxo de trabalho pode ser orquestrado para criar uma nova branch a partir da camada para testar as migrações antes de aplicar a migração final a qualquer ambiente onde os usuários estejam ativos e adicionando dados constantemente.
Juntos, esses fluxos de trabalho garantem que cada PR tenha seu próprio banco de dados e que as branches sejam efêmeras como propriedades do pipeline, e não como disciplinas do desenvolvedor.
Regra. O DBA colabora com os desenvolvedores ao longo de todo o desenvolvimento da funcionalidade, e não apenas no momento da revisão final. A colaboração é assíncrona, diretamente no PR, da mesma forma que outros revisores de código participam.
Por que este é um hábito duradouro agora? O diff do esquema e os resultados dos testes de migração chegam a cada PR automaticamente (consulte Como o fluxo de trabalho é executado no CI acima). O DBA revisa um artefato concreto em seu próprio ritmo. A migração já foi executada em uma branch de CI com dados reais, portanto, o DBA não precisa simular mentalmente a alteração.
Funcionamento:
migrations/, db/, diretórios de teste de esquema).Antipadrão. Não incluir o DBA no fluxo do PR quando existem artefatos legítimos para revisar.
O papel do DBA também ganha novas responsabilidades na administração de políticas e governança em escala de equipe. A Parte 3 abordará esses pontos.
Regra. Todo arquivo SQL, script de migração e teste de esquema vive no mesmo repositório que o código da aplicação. O diff de esquema e os resultados dos testes de migração se juntam ao conjunto de artefatos como saídas no momento do PR.
Por que este é um hábito duradouro agora? O branching adiciona dois novos artefatos ao conjunto: o diff de esquema por PR e os resultados dos testes de migração de esquema por PR. Ambos são gerados pelo CI a partir do estado real da branch. Ambos chegam ao PR como evidências concretas sobre o que foi alterado e como o script de migração de alteração se comportou.
Funcionamento:
migrations/, db/migration/, alembic/versions/, dependente do framework).Antipadrão. Gerar o diff de esquema fora do fluxo do PR (um painel separado que o revisor precisa abrir). O artefato precisa estar onde a revisão acontece. Como as alterações de esquema estão vinculadas às alterações de código, quebrar essa dependência cria problemas downstream para a implantação.
Regra. Sem ALTER TABLE manual em qualquer ambiente. Cada alteração de esquema é um script de migração versionado e integrado. As migrações são idempotentes.
Por que este é um hábito duradouro agora? A regra de migração como artefato permanece inalterada desde 2003. O que há de novo é a disciplina de autoria da idempotência. A mesma migração é executada em várias branches ao longo do ciclo de vida de uma transição, por isso precisa se comportar da mesma forma todas as vezes. Uma migração que falha ao ser reaplicada é um bug.
Funcionamento:
flyway, liquibase, Knex, Alembic ou outros; esses frameworks acompanham quais migrações foram executadas e quais não foram, o que permite que a equipe aplique um comando como flyway migrate, que apenas aplica as alterações que ainda não foram aplicadas (controlando as alterações em uma tabela de metadados)Antipadrão. Uma migração que depende de o esquema estar em um estado intermediário específico devido a alterações locais feitas na branch. A migração deve ser aplicada corretamente em qualquer branch pai que inclua migrações anteriores.
Regra. Cada desenvolvedor, cada PR, cada experimento e cada execução de teste ganha sua própria branch do Lakebase.
Por que este é um hábito duradouro agora? O esforço extra para criar contêineres Docker, instalar servidores de banco de dados locais, adquirir licenças e popular bancos de dados vazios com esquemas existentes e dados de teste não é mais necessário. Um simples comando create-branch do Lakebase cria uma ramificação de um banco de dados de 1 TB no mesmo segundo que um de 1 MB. Nenhum dado é copiado na criação; apenas as páginas modificadas consomem armazenamento. Instâncias por desenvolvedor, por PR e por experimento tornam-se rotina.
Funcionamento:
databricks postgres create-branch ou pelo fluxo branch-create da extensão de SCM.pr.yml), destruídas no merge ou fechamento (merge.yml). Consulte Como o fluxo de trabalho é executado no CI acima para ver os trechos de código de PR e merge.Antipadrão. Compartilhar um banco de dados de desenvolvimento com toda a equipe "por conveniência". A serialização gerada por contenção mencionada na Parte 1 retorna no momento em que as branches são unificadas.
Onde o exemplo de Jen se expande. Sua branch por desenvolvedor foi criada a partir de staging no início da feature. A branch do CI foi criada a partir de staging na abertura do PR. Suas branches de exploração A/B (Prática nº 9) foram criadas a partir de staging em paralelo. Quatro branches para uma única feature, todas em segundos, todas isoladas.
Regra. Cada PR é executado no CI em uma nova branch do Lakebase, com migrações aplicadas e testes executados em um Postgres real.
Por que este é um hábito duradouro agora? O pipeline de CI tem disciplina de migração desde 2010. O que há de novo é o isolamento por pipeline: cada PR ganha sua própria branch, de modo que a integração é executada em dados com formato real, sem contenção.
Funcionamento:
lakebase-migrate apply.Antipadrão. Executar a validação do PR em um ambiente de staging compartilhado. A serialização retorna; a propriedade de isolamento por PR é perdida.
Regra. As alterações de esquema seguem padrões de refatoração nomeados: Dividir coluna, Renomear coluna, Mover coluna, Substituir tipo e assim por diante. Cada um tem mecânicas de transição explícitas (manter o antigo e o novo em paralelo, popular a partir do antigo, trocar leitores, remover o antigo).
Por que este é um hábito duradouro agora? O catálogo de 2006 em databaserefactoring.com nomeia mais de 70 refatorações com exemplos práticos. O que há de novo em 2026 é um local acessível para testar as mecânicas de transição: uma branch de desenvolvedor absorve o teste; a branch do CI verifica; a produção vê apenas o resultado verificado.
Funcionamento:
Antipadrão. Uma alteração de esquema pontual que não mapeia para uma refatoração nomeada. O catálogo com mais de 70 itens cobre os casos comuns; se você estiver fora dele, provavelmente está combinando várias refatorações em uma única migração e deve dividi-las.
Onde o exemplo da Jen vai além. A migração V87 dela é a refatoração de divisão de coluna (Split Column): dividindo inventory_code em location_code, batch_number e serial_number. A página do catálogo em databaserefactoring.com/SplitColumns.html nomeia a mecânica de transição. A branch dela era o espaço de ensaio; a execução de CI do PR foi a verificação.
Regra. Um desenvolvedor pode atualizar o estado do banco de dados de sua branch sob demanda: redefinir para o estado atual da branch pai, criar uma nova branch a partir da produção, descartar uma branch experimental, compartilhar uma branch com um colega de equipe. Tudo em segundos.
Por que este é um hábito duradouro agora? "Sob demanda" em 2026 significa um segundo, isolado, com dados no formato de produção. Nenhuma dessas operações consulta calendários de operações ou filas de DBA.
Mecânica:
databricks postgres create-branch --source production.databricks postgres delete-branch.Antipadrão. Tratar qualquer branch como durável além do seu propósito. A migração é o artefato durável; a branch é o espaço de trabalho.
Regra. Quando o raio de impacto de uma ação destrutiva é zero, o teste destrutivo se torna uma opção diária, em vez de um exercício trimestral.
Por que este é um hábito duradouro agora? Uma branch é redefinida em um segundo. Qualquer coisa que você fizer em uma branch pode ser desfeita criando uma nova a partir da mesma branch pai. Os testes destrutivos deixam de precisar de calendários de operações e portões de aprovação.
Coisas que agora se encaixam em um ciclo normal de recursos:
Efeito cultural. Quando a redefinição não custa nada, as equipes deixam de tratar o banco de dados de teste como um recurso precioso. Os testes podem ser agressivos. A limpeza pode ser ignorada, pois a próxima branch começa do zero.
Onde o exemplo da Jen vai além. Antes de abrir seu PR, ela pegou os dados no formato de produção em sua branch e corrompeu deliberadamente cerca de um por cento dos valores de inventory_code para parecerem casos extremos: dígitos ausentes, espaços incorporados, espaços em branco no final. O tipo de artefato que os dados históricos acumulam. Ela executou sua migração. Duas linhas falharam em sua lógica de substring. Ela corrigiu o script e executou novamente. A branch absorveu o teste destrutivo. A produção nunca o viu.
Regra. Quando dois designs estão em disputa, crie-os em branches paralelas, compare com dados no formato de produção e mantenha a melhor solução.
Por que este é um hábito duradouro agora? O custo por branch é quase zero. Explorar dois designs de esquema não exige mais escolher um com antecedência, e não requer mais um processo de provisionamento que a maioria das equipes não realizaria para uma questão exploratória.
Mecânica:
Antipadrão. Executar protótipos A/B sem registrar a decisão e o raciocínio. As branches desaparecem em um segundo; a decisão de design deve ser permanente.
Onde o exemplo da Jen vai além. Ela considerou dois designs para o recurso de localização/lote/série: três novas colunas na tabela inventory existente, ou uma tabela de busca inventory_attributes separada com chave por inventory_id, prevendo que mais atributos seriam adicionados posteriormente. Ela criou ambos em branches paralelas a partir do ambiente de staging. Ela executou o caminho de leitura do aplicativo em cada uma, mediu o desempenho da consulta em relação aos dados no formato de produção e analisou como cada migração escalaria para volumes de produção. A versão com tabela de busca teve um desempenho pior no caminho de leitura comum porque cada exibição de inventário exigia um join. Ela enviou a versão com colunas, descartou a branch da tabela de busca e deixou uma nota na descrição do PR: Considerou a versão com tabela de busca; rejeitada porque o caminho de leitura comum se torna um join. Reavaliar se mais de cinco atributos forem acumulados.
Nomeamos as sete práticas de 2003 com as limitações que mantiveram cinco delas como aspirações, e as reformulamos para 2026 assim que a ramificação surgiu, além de adicionarmos quatro novas práticas que a ramificação possibilita. São onze práticas no total no novo manual para Desenvolvimento Evolutivo de Banco de Dados, 9 das quais são explicadas acima.
Na Parte 1 – A história da Jen: uma feature, um banco de dados vimos a Jen trabalhar em uma feature: ela emparelhou uma branch de código com uma branch do Lakebase, executou uma migração real em dados no formato de produção em segundos, testou sem mocks, abriu um PR com o diff do esquema publicado inline e realizou o merge com a migração aplicada e as branches efêmeras limpas. A alteração no banco de dados tornou-se parte do desenvolvimento normal.
Na Parte 3 – A equipe da Jen em escala, analisamos o manual com cinquenta desenvolvedores, as responsabilidades evoluídas do DBA na administração e governança de políticas, e os agentes criando branches ao lado da Jen. As práticas nº 10 e nº 11 recebem atenção total lá.
O Guia complementar: passo a passo do plugin cobre a Extensão SCM do Lakebase para VS Code e Cursor.
Um Lakebase App Dev Kit para agentes, com um e-book complementar para profissionais humanos, será lançado em seguida.
(Esta publicação no blog foi traduzida utilizando ferramentas baseadas em inteligência artificial) Publicação original
Assine nosso blog e receba os posts mais recentes diretamente na sua caixa de entrada.