Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Replicação PostgreSQL no Node.js

Atualizado em: 21 de setembro de 2026

Rack de servidores processando fluxos de dados no Node.js

A replicação PostgreSQL no Node.js permite manter um ou mais servidores standby recebendo WAL do primary. As réplicas podem assumir o serviço durante falhas e, quando configuradas como hot standby, atender consultas somente leitura.

Replicação não transforma automaticamente a aplicação em altamente disponível. A API precisa distinguir reads e writes, tolerar lag, lidar com failover, atualizar pools e evitar enviar uma leitura crítica para uma réplica que ainda não recebeu a transação.

Neste guia, você aprenderá streaming replication, read replicas, lag, consistency, failover, replication slots, synchronous replication e padrões de conexão com Node.js.

Como a replicação física funciona?

A documentação oficial de warm standby e streaming replication explica que o primary gera WAL e o standby aplica esses registros continuamente. Streaming envia mudanças sem esperar o segmento WAL completar.

A replicação física copia o cluster em nível de armazenamento. Primary e standby normalmente precisam da mesma major version e arquitetura compatível.

Assíncrona por padrão

O primary confirma COMMIT antes de o standby aplicar a mudança. Existe uma janela de perda se o primary falhar. Também existe atraso para consultas de leitura.

Esse atraso pode ser milissegundos ou minutos, dependendo de rede, carga, I/O, queries longas e capacidade do standby.

Hot standby

Com hot_standby = on, a réplica aceita SELECT durante recovery. Ela continua somente leitura até ser promovida.

Conexões separadas

import pg from 'pg';

export const writerPool = new pg.Pool({
  connectionString: process.env.DATABASE_WRITER_URL,
  max: 10,
  connectionTimeoutMillis: 3000,
  application_name: 'orders-api-writer'
});

export const readerPool = new pg.Pool({
  connectionString: process.env.DATABASE_READER_URL,
  max: 20,
  connectionTimeoutMillis: 3000,
  application_name: 'orders-api-reader'
});

O writer aponta ao primary. O reader aponta a um endpoint de réplicas ou load balancer read-only.

Escolhendo onde ler

Reads adequadas a réplicas:

  • relatórios;
  • dashboards com atraso aceitável;
  • busca e listagens não críticas;
  • exports;
  • analytics operacional.

Reads que devem ir ao primary:

  • imediatamente após escrita;
  • autorização e revogação;
  • estoque e saldo;
  • idempotência;
  • locks e coordenação;
  • confirmação de pagamento.

Read-after-write

Este fluxo pode falhar:

  1. POST cria o pedido no primary.
  2. O cliente recebe 201.
  3. GET consulta a réplica.
  4. A réplica ainda não aplicou o WAL.
  5. A API retorna 404.

Uma estratégia é manter as leituras da sessão no primary por um período curto após uma escrita.

Sticky reads

function choosePool(context) {
  if (context.requiresFreshRead || context.wroteRecently) {
    return writerPool;
  }
  return readerPool;
}

Não confie apenas em um cookie que o cliente possa remover para segurança. A regra de consistência deve estar ligada ao caso de uso.

LSN para consistência

Depois da escrita, obtenha a posição WAL:

const { rows } = await client.query(
  'SELECT pg_current_wal_lsn() AS lsn'
);

Na réplica, compare com:

SELECT pg_last_wal_replay_lsn();

A aplicação pode esperar até o replay alcançar o LSN, com timeout curto, e cair para o primary se necessário. Isso aumenta complexidade; use somente em fluxos que precisam.

Medindo lag

No primary:

SELECT
  application_name,
  client_addr,
  state,
  sync_state,
  sent_lsn,
  write_lsn,
  flush_lsn,
  replay_lsn,
  pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes
FROM pg_stat_replication;

Na réplica:

SELECT
  now() - pg_last_xact_replay_timestamp() AS replay_delay,
  pg_is_in_recovery() AS is_replica;

Lag em tempo pode ser NULL quando não há transações recentes. Combine bytes, timestamps e estado.

Routing por lag

Um health check do reader pode rejeitar a réplica acima do limite:

const result = await readerPool.query(`
  SELECT EXTRACT(EPOCH FROM (
    now() - pg_last_xact_replay_timestamp()
  )) AS lag_seconds
`);

if (Number(result.rows[0].lag_seconds ?? 0) > 5) {
  throw new ReplicaLagError();
}

O limite depende da função. Um dashboard pode aceitar trinta segundos; autorização talvez aceite zero.

Consultas canceladas no standby

Uma query longa pode conflitar com WAL que remove linhas ou altera estruturas. PostgreSQL pode cancelar a consulta para continuar recovery:

ERROR: canceling statement due to conflict with recovery

A aplicação deve reconhecer o erro, limitar duração e, quando seguro, tentar outra réplica ou o primary.

hot_standby_feedback

Essa opção informa ao primary quais linhas ainda são necessárias na réplica, reduzindo cancelamentos. Porém, pode atrasar VACUUM e causar bloat no primary. Monitore dead tuples e transações longas.

max_standby_streaming_delay

Controla quanto o standby pode atrasar replay antes de cancelar queries conflitantes. Aumentar favorece consultas, mas aumenta lag e RPO no failover.

Replication slots

Slots impedem o primary de remover WAL antes de a réplica recebê-lo:

SELECT pg_create_physical_replication_slot('replica_a');

No standby:

primary_slot_name = 'replica_a'

Uma réplica desligada pode fazer o primary acumular WAL até encher o disco. Monitore pg_replication_slots e configure limites como max_slot_wal_keep_size.

WAL archive

Arquivamento contínuo permite recuperar segmentos que não estão mais no primary e também suporta Point-in-Time Recovery. O archive deve continuar acessível mesmo se o primary falhar.

Synchronous replication

Com synchronous_standby_names, commits aguardam confirmação de uma ou mais réplicas:

synchronous_standby_names = 'ANY 1 (replica_a, replica_b)'

Isso reduz perda de dados, mas adiciona latência e pode bloquear writes se não houver standby elegível.

synchronous_commit

O nível pode ser definido por transação:

BEGIN;
SET LOCAL synchronous_commit = 'remote_apply';
UPDATE payments SET status = 'confirmed' WHERE id = $1;
COMMIT;

remote_apply espera a réplica aplicar o commit, permitindo leitura causal em cenários simples. O custo inclui round trip e replay.

Durabilidade seletiva

Use maior garantia para pagamentos e menor para eventos reconstruíveis. A decisão deve ser explícita e documentada, não escolhida aleatoriamente por endpoint.

Failover

Promover um standby:

SELECT pg_promote();

Em produção, um orchestrator deve escolher a melhor réplica, aplicar fencing no primary antigo, atualizar endpoints e reconfigurar standbys.

Fencing

Antes da promoção, impeça o primary antigo de aceitar writes. Sem fencing, uma partição pode criar dois primaries e divergência.

DNS e endpoints

Uma abordagem usa endpoints separados:

postgres-writer.internal
postgres-reader.internal

Após failover, o writer muda para o novo primary. Configure TTL, resolução e lifetime das conexões para não manter sockets ao servidor antigo indefinidamente.

Pool e failover

Conexões existentes não mudam quando o DNS muda. Defina maxLifetimeSeconds, trate erros fatais e recrie pools se a plataforma sinalizar failover.

Consulte Pool PostgreSQL no Node.js e PgBouncer no Node.js.

Retries após failover

Uma transação pode ter sido commitada antes de a conexão cair. Repetir cegamente pode duplicar efeitos. Use idempotency keys e verificação de estado. Veja Idempotência em APIs Node.js.

Transações read-only

BEGIN READ ONLY;
SELECT ...;
COMMIT;

Isso documenta intenção e impede writes acidentais. A réplica já rejeita writes, mas o mesmo código pode rodar no primary durante fallback.

Load balancing de readers

Distribua por capacidade e lag. Round-robin simples pode enviar queries a uma réplica atrasada ou em recovery lento. Health checks precisam incluir replay e capacidade.

Réplicas para jobs

Exports e relatórios pesados podem competir com replay e aumentar lag. Limite concorrência, statement timeout e memória. Para analytics intenso, use um sistema dedicado.

Migrations

Migrations executam no primary e são replicadas. Alterações de schema podem cancelar queries nas réplicas e gerar incompatibilidade durante rollout. Use expand-and-contract. Consulte Migrações de Banco no Node.js.

Backups

Uma réplica não substitui backup. DROP TABLE e dados corrompidos também são replicados. Mantenha base backups, WAL archive e testes de restore.

Segurança

O usuário de replicação possui privilégio elevado para ler WAL. Use uma conta dedicada, SCRAM, TLS e regras restritas no pg_hba.conf:

hostssl replication replicator 10.0.2.15/32 scram-sha-256

Proteja certificados e senhas. Veja Gestão de Segredos no Node.js.

Observabilidade

Monitore:

  • estado streaming, catchup e startup;
  • lag em bytes e tempo;
  • WAL retido por slots;
  • espaço em pg_wal;
  • queries canceladas por recovery;
  • tempo de failover;
  • connections ao primary e replicas;
  • erros read-only e stale reads.

Teste de failover

  1. gere writes e reads;
  2. registre LSN e valores;
  3. isole o primary;
  4. aplique fencing;
  5. promova o standby;
  6. atualize writer endpoint;
  7. confirme pools reconectados;
  8. meça perda e indisponibilidade;
  9. recrie a réplica antiga.

Erros comuns

  • Todas as reads na réplica: read-after-write retorna dado antigo.
  • Slot sem monitoramento: WAL enche o disco.
  • Failover sem fencing: dois primaries aceitam writes.
  • DNS sem reciclar pools: clientes permanecem no host antigo.
  • Retry de transação desconhecida: efeitos são duplicados.
  • hot_standby_feedback sem observar bloat: VACUUM fica prejudicado.
  • Réplicas como backup: exclusões também são copiadas.
  • Lag ignorado: decisões usam estado obsoleto.

Conclusão

A replicação PostgreSQL no Node.js oferece standbys para alta disponibilidade e leitura. Streaming replication mantém as réplicas próximas do primary, mas o atraso e a replicação assíncrona precisam fazer parte do design da aplicação.

Separe writer e readers, direcione leituras críticas ao primary e monitore LSN, lag e slots. Teste failover com fencing e trate conexões e retries de forma idempotente. Assim, a replicação aumenta disponibilidade sem introduzir inconsistência silenciosa.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita