O post da escada de adoção colocou writes multi-região, 100M+ vetores, e milhões de eventos por segundo no Nível 4: não tente. Esse teto continua correto pra uma instância Postgres única.
Este post é sobre o nível intermediário que a maioria dos argumentos 'just use Postgres' pula: o espaço entre 'Postgres vanilla dá conta' e 'trocar por um sistema distribuído'. Tem espaço real entre os dois, e o conselho padrão ('gradue pra uma ferramenta especializada') é frequentemente prematuro. Às vezes a resposta certa é graduar dentro do ecossistema Postgres, usando extensões e sidecars que resolvem uma dor específica sem abrir mão de tudo que o Postgres fez certo: SQL, ACID, a toolchain, o pool de contratação, a história madura de backup.
Quatro eixos de scaling cobrem a maior parte desse terreno intermediário. Aqui está o que eu usaria em cada um, e aproximadamente quando.
Scaling de Conexões: Quando PgBouncer Não Dá Conta
PgBouncer é requisito Nível 2 na escada. Pra maioria dos workloads, é a resposta inteira. Mas o PgBouncer em si é single-threaded e CPU-bound. Quando você está chegando perto de ~10.000 conexões de cliente e o CPU do PgBouncer fica sustentado acima de 70%, você precisa do próximo passo.
Múltiplas instâncias PgBouncer atrás de um load balancer
Simples, confiável, a resposta de manual pra mais um múltiplo de escala. Cada instância de app fala com um PgBouncer local, e o pool atrás deles é dividido entre vários processos PgBouncer. O custo operacional mora principalmente em garantir que os tamanhos de pool ainda somem algo que o Postgres consegue realmente aguentar.
Supavisor
O pooler em Elixir da Supabase, construído especificamente porque PgBouncer esgotou na escala multi-tenant da Supabase. Arquitetura multi-tenant, multi-nó, cloud-native. Vale olhar se você roda Postgres gerenciado em escala ou se está construindo você mesmo um database-as-a-service.
PgCat
Uma alternativa ao PgBouncer escrita em Rust, com sharding, failover e query routing embutidos. Mais opinionado que o PgBouncer; você ganha mais features, se compromete com mais configuração.
Quando graduar
CPU do PgBouncer sustentado acima de 70%, p99 de tempo de espera de conexão subindo, ou uma pegada de deploy onde rodar N sidecars PgBouncer por stack de app virou um cheiro operacional. Se nada disso é verdade, fique no PgBouncer e guarde a migração pra depois.
Scaling de Time-Series: Quando BRIN e Partitioning Não Dão Conta
A escada recomendou índices BRIN mais partitioning declarativo pra time-series. Isso te leva confortavelmente a dezenas de milhões de linhas por dia. Acima disso, você quer TimescaleDB.
O que você ganha por cima do partitioning vanilla:
- Hypertables. Partitioning automático com defaults sensatos, sem gerenciamento manual de partições. Você cria uma hypertable, insere, ela cuida do resto.
- Continuous aggregates. Materialized views que atualizam incrementalmente à medida que novos dados chegam em vez de fazer refresh completo. Se você está servindo dashboards sobre bilhões de pontos, essa é a feature que torna possível.
- Compressão nativa. 10-20x de economia de disco em partições antigas com penalidade mínima em queries. Crítico pra quem mantém mais de alguns meses de dados de alta cardinalidade.
- Políticas de retenção e data tiering como features de primeira classe em vez de cron jobs.
A pegadinha honesta: TimescaleDB tem modelo de licenciamento dual (existe desde 2018, não é uma mudança recente apesar da confusão online). O core é Apache 2.0, enquanto o tier 'Community' de features (compressão nativa, continuous aggregates e suas políticas de refresh, políticas de retenção) vive sob a Timescale License (TSL). A TSL é permissiva pra uso self-hosted; a única atividade que ela proíbe é oferecer o próprio TimescaleDB como database-as-a-service gerenciado.
Vale notar: a empresa rebatizou de Timescale pra Tiger Data em junho de 2025, o que causou confusão online sobre se a licença tinha mudado. Não mudou. Leia a licença antes de se comprometer, especialmente se você redistribui software, mas pra maioria dos times é um não-problema.
Threshold de graduação: você está mantendo mais de 30 a 60 dias de dados numa única instância Postgres, queries contra partições antigas estão mensuravelmente mais lentas que queries contra partições recentes, e você está começando a escrever scripts próprios pra gerenciar o ciclo de vida das partições.
Sharding Horizontal: Quando o Scaling Vertical Acaba
Postgres escala verticalmente pra tamanhos notáveis. Uma instância cloud moderna te dá 96 vCPU e 768GB de RAM sem esforço. Pra maioria dos times esse teto é teórico, nunca vai ser tocado.
Pros times que tocam, Citus é a resposta. Adquirido pela Microsoft em 2019, é o motor por trás do Azure Cosmos DB for PostgreSQL (que a Microsoft está descontinuando pra projetos novos em favor dos elastic clusters do Azure Database for PostgreSQL, também construídos sobre Citus), e disponível como extensão open source que você pode rodar em qualquer infra. Você declara quais tabelas são distribuídas (shardeadas por uma chave escolhida entre nós worker) e quais são tabelas de referência (replicadas pra cada worker pra joins baratos). Queries são paralelizadas entre workers transparentemente quando o planner consegue.
O que o Citus não vai fazer: deixar seu schema distributed-friendly de graça. Você ainda tem que escolher uma shard key por tabela distribuída, e transações cross-shard não são gratuitas. O workload que encaixa melhor é SaaS multi-tenant onde você sharda por tenant ID, porque queries cross-tenant são raras e queries intra-tenant ficam locais a um único shard. Joins complexos cross-entidade entre shards é onde você sente as restrições.
Threshold de graduação: seu primary está consistentemente CPU-bound, você não consegue comprar uma máquina maior ou a maior é absurdamente cara, ou seu volume de escrita passou do que o WAL de um único nó aguenta.
Scaling de Leitura: Quando Um Primary Não Consegue Servir Suas Leituras
Replicação em streaming (física) te dá hot standbys. Ela envia o WAL byte a byte do primary pra réplica, então a réplica é sempre uma cópia exata do primary, na mesma versão maior do Postgres. Você pode rotear tráfego de leitura pra eles. Território bem pisado, suportado out of the box desde Postgres 9.
Replicação lógica é a prima subestimada. Em vez de transmitir os bytes do WAL, ela decodifica o WAL em eventos no nível de linha (INSERT/UPDATE/DELETE) e envia esses eventos pra um subscriber. O subscriber pode estar numa versão maior diferente do Postgres, pode assinar só algumas tabelas, e pode ter os próprios índices. A infraestrutura subjacente de logical decoding existe no Postgres desde 9.4, mas a replicação lógica nativa publish/subscribe chegou no Postgres 10 e é o que a maioria dos times realmente usa hoje. Casos de uso que vale conhecer:
- Réplica analítica dedicada com índices diferentes otimizados pra queries de reporting. Seu primary OLTP fica leve; seus relatórios rodam numa réplica com índices aggregate-friendly.
- Upgrades de versão maior com zero downtime. Replique da v15 pra v17, verifique, vire. Sem janela longa de manutenção.
- CDC sem Debezium. Replicação lógica já é CDC no nível do Postgres. Pra muitos casos downstream (índice de busca, sync de data warehouse), é suficiente.
- Sharding seletivo por peso de tenant. Tenants quentes vão pra uma máquina maior via replicação lógica só das linhas deles.
Ferramentas que vale conhecer: CREATE PUBLICATION / CREATE SUBSCRIPTION nativos, e pglogical pros cenários que o tooling nativo não cobre.
Quando Realmente Sair
O teste honesto é se o teto que você está batendo é operacional ou estrutural.
Tetos operacionais ficam no ecossistema Postgres:
- Sem conexões. Problema de pooler.
- Sem disco por causa das partições. Problema de TimescaleDB.
- Sem CPU no primary. Problema de Citus ou de scaling vertical.
- Relatórios lentos. Problema de réplica de leitura.
Tetos estruturais significam que é hora de adicionar uma ferramenta especializada:
- Latência sub-milissegundo sob contenção extrema de escrita. Stores in-memory (Redis, DragonflyDB) existem porque memória não é disco.
- Writes ativo-ativo multi-região verdadeiros com consistência forte. CockroachDB, Spanner e YugabyteDB resolvem o problema de consenso distribuído nativamente. Postgres não, e grudar isso por cima com tooling de terceiros troca um conjunto de problemas por um pior.
- Workloads analíticos reais em bilhões de linhas. ClickHouse, DuckDB e Snowflake são arquiteturas genuinamente diferentes por um motivo. Extensões como pg_duckdb e ParadeDB estreitam o gap pra necessidades OLAP menores, mas não fecham no topo.
- Event streaming na escala Kafka. Se você genuinamente precisa de milhões de eventos por segundo com replay, partitioning, consumer groups e fan-out, use Kafka.
O teste que uso: se você não consegue nomear a extensão ou sidecar específico que resolve seu problema dentro do Postgres, e o teto que está batendo é arquitetural em vez de operacional, é hora de adicionar outra ferramenta. Se você consegue nomear a extensão que resolve (e especialmente se ela tem licença razoável e comunidade mantida), fique.
A maioria dos times decide que precisa de um banco distribuído mais ou menos um ano antes de realmente precisar. Estender o Postgres com a extensão certa compra de volta a maior parte desse ano, geralmente a uma fração do custo.
Referências
- PgBouncer (oficial): https://www.pgbouncer.org/
- Supavisor (Supabase, pooler multi-tenant em Elixir): https://github.com/supabase/supavisor
- PgCat (pooler em Rust com sharding e query routing): https://github.com/postgresml/pgcat
- TimescaleDB no GitHub (extensão open source, mantida pela Tiger Data): https://github.com/timescale/timescaledb
- Termos de licença TimescaleDB (Apache 2.0 + TSL, oficial): https://www.tigerdata.com/legal/licenses
- Anúncio de rebranding Tiger Data (junho de 2025): https://www.tigerdata.com/blog/timescale-becomes-tigerdata
- Docs oficiais TimescaleDB (hypertables, continuous aggregates, compressão): https://docs.tigerdata.com/
- Citus no GitHub (extensão Postgres distribuída open source): https://github.com/citusdata/citus
- Microsoft adquire Citus Data (anúncio de janeiro de 2019): https://blogs.microsoft.com/blog/2019/01/24/microsoft-acquires-citus-data-re-affirming-its-commitment-to-open-source-and-accelerating-azure-postgresql-performance-and-scale/
- Azure Cosmos DB for PostgreSQL (Citus gerenciado): https://learn.microsoft.com/en-us/azure/cosmos-db/postgresql/introduction
- Replicação streaming física (docs PostgreSQL, desde PG 9): https://www.postgresql.org/docs/current/warm-standby.html
- Replicação lógica (docs PostgreSQL, desde PG 10): https://www.postgresql.org/docs/current/logical-replication.html
- pglogical (2ndQuadrant / EDB, suporte a versões mais amplo): https://github.com/2ndQuadrant/pglogical
- ParadeDB (extensão analítica nativa Postgres): https://www.paradedb.com/
- CockroachDB (ativo-ativo multi-região): https://www.cockroachlabs.com/
- YugabyteDB (SQL distribuído): https://www.yugabyte.com/
- Google Spanner (SQL distribuído globalmente): https://cloud.google.com/spanner
- ClickHouse (DB analítico em grande escala): https://clickhouse.com/
- DuckDB (DB analítico embarcado): https://duckdb.org/
- Snowflake (data warehouse na nuvem): https://www.snowflake.com/