Self-Hosting Postgres: Os Números Reais Além do Hype Cloud

Análise profunda dos custos reais de self-hosting PostgreSQL vs RDS/Aurora: benchmarks, overhead operacional, break-even points e quando a migração realmente vale a pena.

Self-Hosting Postgres: Os Números Reais que os Estudos de Caso Escondem

Quando a conta de RDS ultrapassou $8.000/mês (R$42.000 no câmbio atual), a discussão sobre self-hosting finalmente ganhou tração real na empresa. Não por romantismo de controle total ou aversão filosófica ao vendor lock-in, mas porque alguém da diretoria viu a fatura e perguntou: “Por que gastamos o equivalente a dois desenvolvedores seniores rodando um banco de dados?”

Esse cenário está se repetindo em 2025 com frequência suficiente para gerar artigos no Hacker News com centenas de comentários. Empresas que cresceram durante a era de dinheiro barato estão descobrindo que managed databases custam 2-3x mais que bare metal para workloads estáveis. A promessa de “abstrair complexidade” começa a parecer cara quando você tem um time técnico competente.

Os casos de estudo que viralizam geralmente mostram só o lado positivo da economia. Ninguém publica post-mortem sobre como perderam dois dias de dados porque o backup restore tinha um bug silencioso, ou quanto custou contratar o DBA que realmente entende como debugar replication lag às 3 da manhã.

A Matemática Real da Migração (e Por Que Ela Não é Tão Simples)

RDS adiciona um markup de 50-100% sobre uma instância EC2 equivalente. Uma r6i.4xlarge no RDS custa aproximadamente o dobro da mesma instância EC2, em troca de backups automáticos, high availability, e patching gerenciado.

O break-even point financeiro típico está em $3.000-5.000/mês de gastos RDS — cerca de R$16.000-26.000. Abaixo disso, o custo de setup e overhead operacional provavelmente não justifica a migração. Acima, os números começam a fazer sentido. A Discourse reportou economia de ~$1.200/mês (R$6.300) migrando de um RDS r5.2xlarge para bare metal em 2019. Não é revolucionário, mas em escala de startup é equivalente a meio desenvolvedor junior.

Aqui está o gotcha que ninguém menciona nos primeiros slides: você precisa provisionar 30-40% de capacidade extra para overhead operacional. Replicação síncrona, backups contínuos, e um failover node idle comem recursos. Se você está rodando 100GB no RDS, planeje 140GB de storage efetivo no self-hosted. Se está consumindo 32GB de RAM, vai precisar de ~45GB para rodar confortavelmente com os mesmos níveis de performance e disponibilidade.

O cálculo conservador para self-hosting em bare metal:

  • Hardware/infra base: 40-60% economia vs RDS
  • Monitoramento dedicado: $500-2.000/mês (R$2.600-10.500) em ferramentas
  • 0.5-1 FTE DevOps focado em database operations
  • Infraestrutura de disaster recovery (réplica em região diferente)
  • Buffer de 20-30% para crescimento sem reprovisionamento urgente

Economias reportadas em empresas mid-size ficam entre 40-60% após migração completa. “Após migração completa” significa meses de trabalho, não semanas. GitLab documentou sua migração de RDS para self-hosted entre 2017-2018, reportando ganhos significativos de controle sobre tuning e custos, mas admitindo francamente que a complexidade operacional aumentou substancialmente.

Performance: Onde os Benchmarks Mentem (e Onde Não Mentem)

Aurora PostgreSQL-compatible tem latency 10-30% maior que RDS PostgreSQL standard devido à arquitetura de storage distribuído. Isso não é bug, é arquitetura: Aurora sacrifica latência absoluta por capacidade de escalabilidade extrema (até 15 read replicas, storage auto-scaling até 128TB). Para a maioria dos workloads transacionais, esses 10-30% são imperceptíveis. Para aplicações com p99 latency requirements agressivos? Inaceitáveis.

Benchmarks públicos mostram que um r6i.4xlarge no RDS sustenta ~20.000 TPS em workload write-heavy. O equivalente bare metal (32vCPU, NVMe local) atinge ~35.000 TPS no mesmo workload. Diferença de 75% de throughput.

Mas esses números variam 200-300% baseado no padrão específico do seu workload. Read-heavy com queries complexas? A diferença pode ser marginal. Write-heavy com transações pequenas? Self-hosted com NVMe local destrói qualquer opção cloud.

Benchmark do operador Zalando para Kubernetes: 10k TPS sustained em bare metal vs ~7k em cloud block storage (io2). A diferença não é o PostgreSQL — é o storage layer. Local SSDs com hostPath/LocalPV no Kubernetes entregam 40-60% melhor IOPS que network-attached storage. Se você está rodando PostgreSQL em K8s (e muita gente está), eliminar network overlays usando hostNetwork mode reduz latency em 15-20%.

Self-hosted bare metal com NVMe moderno entrega p99 latency <1ms. Aurora entrega p99 ~5-10ms segundo benchmarks independentes de 2023. Para contexto brasileiro: adicione 300ms de latency se seu application server está em São Paulo e seu RDS em us-east-1. Subitamente aquele p99 de 10ms vira 310ms, e você está debugando timeout issues que não existiriam com database local.

PostgreSQL 14+ com io_uring (kernel 5.1+) melhora latency em 20-25% em NVMe. Esse ganho é “grátis” em self-hosted se você controla o kernel. No RDS, você espera até que a AWS atualize a AMI base, o que pode levar meses após release upstream.

O Custo Real de “Você é o DBA Agora”

Connection pooling via PgBouncer reduz consumo de RAM em ~70%: 1000 connections diretas consomem 5-10GB de RAM dependendo de work_mem. Com pooling, você roda 100 connections reais para atender a mesma carga. Isso é básico para qualquer deployment sério. No RDS você pode ser preguiçoso e não implementar. No self-hosted, é obrigatório desde o dia 1.

O stack operacional padrão para PostgreSQL self-hosted em 2025:

  • High Availability: Patroni ou repmgr para automatic failover
  • Backup: pgBackRest ou wal-g com continuous WAL archiving (RPO <5min, RTO 15-60min)
  • Connection Pooling: PgBouncer (mandatório, não opcional)
  • Monitoring: Prometheus + postgres_exporter, alertas customizados no replication lag

Backup overhead consome 10-15% de storage adicional. WAL archiving precisa rodar 24/7, e você precisa testar restore regularmente. Não simular restore — executar restore real em ambiente staging, cronometrar, documentar. Quantas empresas fazem isso mensalmente? Menos de 10%, na minha experiência.

Vacuum e autovacuum tuning não são opcionais. No RDS, configurações default são conservadoras e geralmente funcionam. No self-hosted, bloat é problema real que requer monitoramento contínuo de dead tuples ratio. Já vi databases self-hosted crescerem 40% de tamanho desnecessariamente porque ninguém configurou autovacuum_vacuum_cost_limit adequadamente.

Tuning obrigatório que você não escapa:

shared_buffers = 25% da RAM total
effective_cache_size = 50-75% da RAM total
work_mem = depende de quantas queries simultâneas (começar conservador)
maintenance_work_mem = 1-2GB para operações de manutenção

Isso não é rocket science, mas requer entendimento de como PostgreSQL usa memória. Configurar errado resulta em performance 50% pior que deveria ser, e você vai desperdiçar semanas debugando queries que não são o problema.

StatefulSets no Kubernetes para PostgreSQL exigem pod affinity rules para garantir que réplicas não coexistam no mesmo node. Backup/restore é mais complexo que em deployment tradicional. Upgrade requer rolling restart cuidadoso. O Zalando postgres-operator (18k+ stars no GitHub) e Crunchy Data PGO v5.x são maduros e resolvem esses problemas, mas adicionar operador Kubernetes ao stack significa mais uma camada para debugar quando algo quebra às 2 da manhã.

Replication lag >1 segundo indica problema sério. Monitoramento via pg_stat_replication precisa estar configurado, com alertas. Não apenas dashboards bonitos que ninguém olha. Troubleshooting de lag envolve entender network throughput, disk I/O na replica, e configuração de synchronous vs asynchronous replication. No RDS, você abre ticket no suporte. No self-hosted, você é o suporte.

Quando Self-Hosting Realmente Vale a Pena

Se seus custos de RDS estão abaixo de $3.000/mês, provavelmente não vale. O tempo do time técnico para setup, manutenção e eventual incident response custa mais que a economia. Essa é a resposta honesta que poucos artigos dão.

Acima de $5.000/mês, os números começam a fazer sentido, mas apenas se você tem:

Pelo menos um DevOps/SRE com 3-5 anos de experiência específica em PostgreSQL. Não basta ser “bom com Linux”. Database tuning é especialização própria.

On-call 24/7 estruturado. Não pode ser “o desenvolvedor full-stack que sabe mais de database”. Precisa ser rotação formal, com runbooks, e compensação adequada.

Workload estável o suficiente para justificar investimento em tuning. Se seu tráfego varia 10x entre picos e vales, managed database que escala automaticamente pode ser mais barato operacionalmente.

O downtime típico para cutover de migração é 4-8 horas usando logical replication (pg_logical ou pglogical). Você pode reduzir para minutos com planejamento cuidadoso, mas adiciona complexidade. A maioria das empresas agenda janela de manutenção e aceita as 4-8 horas porque é operacionalmente mais seguro.

Validação de data integrity pós-migração é crítica e consome tempo. Row counts não são suficientes — você precisa comparar checksums, testar queries críticas, validar foreign keys. Discourse levou duas semanas de validação em staging antes de migrar produção.

Rollback strategy precisa estar definida antes de começar. Se algo der errado durante cutover, quanto tempo leva para voltar ao RDS? Você tem os backups necessários? Testou restore? Na prática, maioria dos rollbacks pós-migração leva 2-4 horas porque envolve restore e repoint de conexões.

Aurora tem vantagens específicas difíceis de replicar: 15 read replicas, failover <30 segundos, throughput 1.5-2x superior em cargas OLTP específicas (não 3x como marketing da AWS sugere, mas benchmarks independentes confirmam 1.5-2x). Se você precisa dessas características, self-hosting vai exigir arquitetura significativamente mais complexa.

Para contexto brasileiro: se você está em São Paulo, self-hosting em datacenter local (Equinix SP2, por exemplo) elimina a latência trans-atlântica mas adiciona complexidade de contratos de colo, SLA de energia, e contingência de conectividade. RDS em sa-east-1 (São Paulo) é mais caro que us-east-1 (~20% markup regional), tornando o break-even point mais favorável ao self-hosting localmente.


Self-hosting PostgreSQL não é statement tecnológico ou questão de princípios. É planilha de Excel. Se os números fecham, sua equipe tem skill adequado, e você aceita o trade-off de complexidade operacional por controle e economia, faz sentido. Se você está migrando “porque é mais tech” ou “para aprender”, vai aprender da maneira cara — em produção, às 3 da manhã, quando o standby não promoveu e você precisa entender por que o Patroni não triggerou failover automático.

Os casos de estudo que mostram 60% de economia raramente mencionam os três meses de trabalho para chegar lá, ou o custo de oportunidade de não ter desenvolvido features nesse período. Economias são reais, mas vêm com custos que não aparecem na fatura mensal de cloud. A decisão honesta não é “cloud vs self-hosted”, é “quanto vale nosso tempo técnico vs quanto estamos gastando, e temos skill necessário para não transformar isso em pesadelo operacional”.


← Voltar para home