Como fazer upgrade major do PostgreSQL sem downtime em cluster distribuído com Spock
Ahsan Hadi, da pgEdge, testou a migração de PostgreSQL 17 para 18 num cluster multi-master com Spock e documentou as duas armadilhas que não aparecem em nenhum status check.
O problema que todo upgrade major carrega
Trocar a versão major do PostgreSQL↳PostgreSQL11 conteúdosPostgreSQL via SSL com GolangData · abr 20195 itens legais sobre data types do PostgreSQLData · mar 20195 serviços gratuitos na cloud para bancos de dados PostgresData · fev 2025Ver tudo em Data → em um primary único sempre trouxe a mesma pergunta: quanto tempo a aplicação pode ficar fora do ar? O pg_upgrade --link é rápido, mas ainda é uma parada, e depois dela é preciso reconstruir ou ressincronizar as réplicas. Ahsan Hadi, da pgEdge, parte desse incômodo em post publicado em 23 de outubro de 2026 no blog da empresa, relatando um teste de upgrade de PostgreSQL 17.10 para 18.6 num cluster distribuído com Spock, a extensão open-source de replicação lógica multi-master da pgEdge.
A ideia central: em vez de atualizar um nó parado, você sobe um nó novo já na versão nova, deixa ele entrar no cluster recebendo e enviando mudanças, migra o tráfego para ele e só então aposenta o nó antigo. Repete isso nó a nó até o cluster inteiro estar na versão nova, sem que a aplicação perca, em nenhum momento, um endpoint que aceite escrita.
Por que multi-master muda o cálculo
Num cluster Spock, todo nó aceita escrita e replica para os outros via lógica, não via WAL físico. Isso é o que permite adicionar um nó novo sem derrubar nada: ele entra como mais um participante do multi-master, não como substituto temporário de quem já está no ar.
É diferente do caminho que a comunidade PostgreSQL está construindo para a versão 19, que combina pg_createsubscriber, pg_upgrade e a sincronização de sequences num esquema blue-green. Hadi é direto sobre essa alternativa:
Isso não é, de fato, um upgrade de zero downtime, porque as escritas precisam ser pausadas por um determinado período.
This is not really ZERO downtime upgrade because the writes need to be paused for a certain period of time.Ahsan Hadi, pgEdge
No cutover do blue-green do PostgreSQL 19, as escritas param enquanto as últimas mudanças drenam, as sequences sincronizam e a aplicação troca de lado. Para uma aplicação crítica, essa pausa ainda é uma indisponibilidade, mesmo que curta.
O roteiro testado em laboratório
Hadi documentou o processo num cluster de dois nós (n1 e n2, ambos PostgreSQL 17.10 com Spock 5.0.12), rodando em VMs Rocky Linux↳Linux34 conteúdosKali Linux em um Servidor VPS: como, quando e por que usar?DevSecOps · dez 2024Construindo um Windows Service ou Linux Daemon com Worker Service & .NET Core – Parte 2Dev (Back & Front) · jul 2020Criando uma WebApi utilizando .NET, Linux e VSCodeDev (Back & Front) · ago 2019Ver tudo em DevSecOps → ARM64, e adicionou um terceiro nó (n3) em PostgreSQL 18.6 ao lado deles. Para cada nó que precisa subir de versão, o laço é sempre o mesmo:

- Construir um nó novo na versão alvo, com a mesma versão do Spock do cluster.
- Adicioná-lo com o Zodan, um conjunto de scripts SQL que acompanha o Spock e chama
spock.add_nodepara copiar schema e dados de um nó existente e montar as subscrições nos dois sentidos, sem parar o cluster. - Verificar que o nó novo recebe e também envia mudanças.
- Se o nó antigo tinha uma réplica física, construir uma réplica nova a partir do nó novo (ele usou o Patroni para isso).
- Mover o tráfego da aplicação e remover o nó antigo com
spock.remove_node.
Antes de tocar em qualquer coisa, é preciso checar a versão do PostgreSQL, a versão do Spock, os nomes de nó e os roles existentes com \du. O Zodan recusa a adição se a versão do Spock ou os roles não baterem entre o nó de origem e o novo.
Também é obrigatório desligar a replicação automática de DDL em todos os nós existentes antes de começar:
ALTER SYSTEM SET spock.enable_ddl_replication = off;
SELECT pg_reload_conf();Isso tem um efeito colateral direto na operação: nenhuma mudança de schema pode vir da aplicação até a migração terminar. É preciso planejar a janela de upgrade em torno do calendário de deploys.
As duas armadilhas que o status check não mostra
O ponto mais importante do relato de Hadi não está na automação do Zodan, mas em dois comportamentos silenciosos que ele só percebeu testando escrita de ponta a ponta, mesmo com todas as subscrições marcadas como replicating.
Replication sets vazios no nó novo. Com a replicação de DDL desligada, a cópia de estrutura cria as tabelas no nó novo, mas nada adiciona essas tabelas aos conjuntos de replicação dele. O nó recebe tudo e publica nada. Segundo o relato, em um upgrade real escritas feitas no nó novo nunca chegariam ao resto do cluster, e sumiriam de vez assim que o nó antigo fosse aposentado. A correção é copiar a associação de replication set do nó de origem:
psql -h 192.168.169.158 -p 5432 -d testdb -Atc \
"SELECT format('SELECT spock.repset_add_table(%L, %L, false);', set_name, quote_ident(nspname)||'.'||quote_ident(relname)) FROM spock.tables WHERE set_name IS NOT NULL;" > n3_repsets.sql
psql -p 5442 -d testdb -v ON_ERROR_STOP=1 -f n3_repsets.sqlSlots sem failover = true. Os slots lógicos que spock.add_node cria no nó novo, aqueles de onde os outros nós puxam mudanças, saem com failover = false. A sincronização nativa de slots do PostgreSQL ignora esses slots, o que significa que, após uma promoção de réplica, os outros nós perderiam a posição de leitura. A correção exige pausar as subscrições, alterar o slot numa conexão de replicação e religar:
SELECT spock.sub_disable('sub_n3_n1', true);
-- em conexão de replicação:
ALTER_REPLICATION_SLOT spk_testdb_n3_sub_n3_n1 (FAILOVER true);
SELECT spock.sub_enable('sub_n3_n1', true);Patroni reescreve a configuração do Spock sem avisar
Para reconstruir a réplica física do nó novo, Hadi colocou o n3 sob o Patroni em vez de rodar pg_basebackup manualmente. O Patroni assumiu a instância em execução e silenciosamente trocou shared_preload_libraries de spock para None, track_commit_timestamp de on para off e wal_level de logical para replica.
Nada quebra até o próximo restart. Depois disso, o nó ou se recusa a subir ou sobe sem o Spock. O Patroni só aceita parâmetros como wal_level vindos da configuração do cluster no etcd, então é preciso registrar cada requisito do Spock lá antes de reiniciar qualquer coisa:
patronictl -c ~/patroni/n3.yml edit-config --force \
-p wal_level=logical -p track_commit_timestamp=on \
-p shared_preload_libraries=spock -p max_worker_processes=16 \
-p max_wal_senders=10 -p max_replication_slots=10 \
-p max_active_replication_origins=10 \
-p sync_replication_slots=on -p hot_standby_feedback=onComo esses valores ficam gravados no etcd, a réplica que o Patroni constrói em seguida com pg_basebackup já herda a configuração certa, sem precisar do mesmo ajuste manual.
O que muda para quem mantém o banco em produção
Para quem já roda PostgreSQL com alta disponibilidade baseada em WAL físico (Patroni, repmgr, pg_auto_failover), esse fluxo exige repensar a topologia: o ganho de zero downtime no upgrade vem de já ter multi-master com Spock rodando antes de precisar do upgrade, não é algo que se liga na véspera da migração.
Alguns pontos de atenção saem direto do relato:
- Trocar a versão não dispensa testar escrita nos dois sentidos antes de remover qualquer nó antigo: o status de subscrição sozinho não detecta um nó que só recebe e nunca publica.
- O DSN passado em
spock.add_nodefica armazenado emspock.node_interfaceem todos os nós do cluster, o que reforça manter senha fora da string de conexão, via~/.pgpass. - Em produção, apontar o DSN do Spock para um VIP ou nome DNS, não para o IP do servidor, é o que permite a subscrição sobreviver a um failover do Patroni.
- Quem já roda o pgEdge Control Plane, a ferramenta de orquestração declarativa da própria pgEdge, não precisa repetir esse procedimento manual: a mesma lógica de adicionar nó com zero downtime está embutida no fluxo de upgrade de versão major da ferramenta.
Quando esse caminho não compensa
O procedimento todo pressupõe que a aplicação já tolera, ou já usa, um cluster multi-master com conflitos de escrita resolvidos pela lógica do Spock, o que é uma mudança de arquitetura bem maior do que simplesmente trocar a versão do banco. Para quem roda um primary único com uma ou duas réplicas físicas e não tem outro motivo de negócio para ir a multi-master, o blue-green nativo que chega no PostgreSQL 19 (ainda com sua pausa de escrita no cutover) tende a ser o caminho mais simples, mesmo não sendo verdadeiramente zero downtime.
Hadi também deixa um aviso: ele ainda não testou um failover completo nesse cenário multi-nó durante o upgrade, e promete um post de acompanhamento. Até lá, vale tratar o roteiro como validado para o caminho feliz (adicionar nó, replicar nos dois sentidos, promover standby), mas não como coberto para o cenário de falha no meio da janela de migração.
Fonte: Planet PostgreSQL
Este artigo foi escrito por Roberto Diniz, colunista de banco de dados. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.
PostgreSQL 19 traz pg_stat_recovery e leitura de WAL em backups tar
Entre os commits revisados por Pavel Luzanov, da Postgres Professional, estão verificação de backup em tar, uma view única para monitorar recovery e indicador de réplica direto no prompt do psql.













