Talk · Postgres + Docker

Database branching estilo Neon

Homolog é o tronco. Por branch de código: clone Copy-on-Write, migration só no filho, validar, destroy. Teoria Neon + o que dá pra aproximar no Docker.

  • Postgres CoW
  • Homolog = tronco
  • N branches / migration
  • Docker

01 · Teoria

Como o Neon faz branching

Compute separado do storage (pageserver). Um branch é um ponteiro para um LSN — não uma cópia cheia do disco.

Páginas 8 KB

Compartilhadas com o pai até divergir. Leitura do tronco; DDL/DML escrevem páginas só no filho (delta).

Create ≈ metadado

Criar branch é quase instantâneo: storage do filho começa ~0 até o primeiro write. Não há merge Git-like.

Reset from parent sobrescreve o filho. O pai nunca “vê” as mudanças da branch — e não existe merge de dados estilo Git.

02 · Diagrama

Tronco → clone → migration → destroy

Homolog permanece limpo. Cada feature ganha um clone CoW em porta própria.

flowchart TD
  H["homolog · tronco"] --> S["snapshot @homolog"]
  S --> X["clone feat-x :5433"]
  S --> Y["clone feat-y :5434"]
  X --> MX["migration só no clone"]
  Y --> MY["migration só no clone"]
  MX --> DX["validar → destroy"]
  MY --> DY["validar → destroy"]
          

Fluxo prático: N branches por migration, tronco intacto.

CoW de páginas 8 KB

Páginas compartilhadas com o pai até o primeiro write no filho.

flowchart LR
  subgraph Pai["tronco / pai"]
    P1["page A"]
    P2["page B"]
    P3["page C"]
  end
  subgraph Filho["branch filha"]
    F1["page A · shared"]
    F2["page B' · escrita"]
    F3["page C · shared"]
  end
  P1 -.->|leitura| F1
  P2 -->|CoW no write| F2
  P3 -.->|leitura| F3
          

Só a página modificada vira cópia no filho; o resto aponta pro pai.

03 · Contraste

Neon vs Postgres vanilla / Docker sozinho

Vanilla não faz branching CoW sem pageserver. TEMPLATE clássico, dump e clone de volume sem CoW não são o mesmo.

Neon (produto)

CoW real via pageserver

  • Branch = ponteiro LSN
  • Páginas 8 KB compartilhadas
  • Create branch ≈ metadado
  • Compute por branch
Vanilla / Docker puro

Sem pageserver = sem isso

  • CREATE DATABASE … TEMPLATE clássico ≠ CoW
  • Dump/restore = cópia cheia
  • Clone de volume sem FS CoW = cópia
  • Não inventa branching no Postgres OSS sozinho

04 · Self-hosted

Aproximações no Docker / on-prem

Caminhos que chegam perto — com trade-offs claros.

Caminho CoW real? Quando usar
DBLab (Postgres.ai) + ZFS Sim · snapshot/clone Servidor Linux / VM com ZFS — mais próximo de produto
Postgres 18 + file_copy_method=clone + TEMPLATE FILE_COPY Sim no FS Mesmo cluster; precisa XFS reflink / ZFS / Btrfs
pgoverlay (OverlayFS) Sim · OverlayFS Laptop Docker sem ZFS; 1 container por branch
Neon Local CoW na nuvem Neon Só se homolog puder morar no Neon
Dump / TEMPLATE sem clone Não Fallback se FS = ext4 na VM do Desktop

DBLab + ZFS

Thin clone de produto. Snapshot → clone → porta por feature.

PG18 FILE_COPY

Branches = databases no mesmo postmaster. Reflink no FS.

pgoverlay

OverlayFS no laptop. Bom quando não há ZFS no Docker Desktop.

05 · Recomendação

O que usar onde

Laptop · Docker Desktop

pgoverlay ou PG18 TEMPLATE CLONE se o data dir estiver em FS com reflink. Colima / Linux nativo ajuda; Desktop em ext4 da VM = cópia cheia.

Servidor Linux · homolog grande

DBLab + ZFS (ou tendb em cima). Snapshot @homolog → clone → porta → migration → destroy.

06 · Fluxo servidor

Fluxo prático · homolog + clones

homolog (ZFS dataset, refresh periódico)
  └── snapshot @homolog
        ├── clone feat-xpostgres:5433
        └── clone feat-ypostgres:5434
  1. Criar clone do snapshot

    zfs clone / dblab clone create a partir de @homolog.

  2. Migrator só na URL do clone

    Flyway / EF / Liquibase apontam somente para a connection string do filho.

  3. Validar

    Testes, smoke, revisão de schema — no clone isolado.

  4. Destroy

    Destruir ou resetar o clone. Tronco permanece limpo.

Regra de ouro: nunca apontar o migrator da feature no volume pai.

07 · Fluxo PG18

Mesmo cluster · TEMPLATE FILE_COPY

Manter homolog (ou template atualizado offline, sem conexões na hora do create).

# postgresql.conf
file_copy_method = clone

-- SQL
CREATE DATABASE branch_<git>
  TEMPLATE homolog
  STRATEGY FILE_COPY;

-- app / migration → dbname=branch_<git>
DROP DATABASE branch_<git>;
Caveat: mesmo postmaster — CPU e locks compartilhados. Bom pra migration; ruim pra isolamento forte de carga.

08 · Limites

O que você ainda não ganha vs Neon

Produto gerenciado

Scale-to-zero por branch, TB instantâneo gerenciado, billing de delta na nuvem.

Merge + pageserver DIY

Não há merge de dados. Self-host pageserver existe (cargo neon), mas não é Compose de produção.

Aproximações self-hosted cobrem o caso “N clones pra validar migration”. Não substituem o produto Neon completo.