8 min read
postgres
arquitectura
escalabilidade
bases-dados
saas

Migrating from PostgreSQL to Distributed Database: When and How to Decide

Is Postgres enough? Discover when to migrate to distributed systems, real-world pitfalls, and the criteria that decide between Postgres, CockroachDB, Cassandra, or YugaByte.

Migrating from PostgreSQL to Distributed Database: When and How to Decide

Migrating from PostgreSQL to Distributed Database: When and How to Decide

TL;DR

  • PostgreSQL can scale vertically to 100k+ TPS with tuning; most B2B SaaS never hits real limits before operational issues arise.
  • Distribution doesn't solve network latency (CockroachDB: +50-100ms p99 vs local Postgres); it solves geographic partitioning, write-heavy workloads, and high availability without manual failover.
  • Migration costs 4-8 weeks of engineering, requires query rewrites (cross-partition JOINs are expensive), and introduces operational complexity: distributed backups, consistency tuning, distributed debugging.
  • Real case: a fintech platform with 2M transactions/day discovered the bottleneck was misconfigured connection pooling (600 unnecessary connections), not database capacity. 3 hours of Postgres tuning resolved it, not migration.
  • Objective criterion: migrate when two of these coexist: (1) >50k sustained TPS, (2) data across 3+ regions with acceptable write latency <200ms, (3) write-scaling beyond read replicas, (4) SLA of 99.95%+ without maintenance windows.

PostgreSQL is one of the most reliable technologies in production because it solves 95% of scaling problems through existing knobs before demanding architectural change.

But there's a common illusion in the industry: believing that "growth" necessarily means switching technology.

In this article we'll clarify when migrating to a distributed database (CockroachDB, YugaByte, Cassandra) is a real technical decision versus unnecessary engineering exercise. We include concrete criteria, pitfalls we've seen in production, and why your problem probably isn't Postgres.


What PostgreSQL Does Well (Very Well, Actually)

Before looking elsewhere, let's understand why Postgres remains the default choice for B2B SaaS in 2025.

A well-tuned PostgreSQL 16 server can achieve:

  • 50k+ TPS in writes with NVME SSDs, sufficient memory, and optimised WAL (standard TPC-B test).
  • Sub-millisecond p50 latency on simple queries (SELECT, INDEX lookups); p99 stays at 5-15ms with correct pooling.
  • Horizontal read scalability via streaming replication (9 replicas easily; Patroni + HAProxy automates failover).
  • Full ACID with serializable isolation (vs eventual consistency of distributed systems).
  • Complex queries with JOINs, aggregations, window functions without architectural penalty.
  • Schema flexibility via JSON/JSONB; documents and structured data coexist.

This covers >90% of SaaS applications that assume they're in "scaling problems" when they're actually in "configuration problems".

A concrete case we saw: a billing platform processed 50k events/day and believed it was approaching Postgres limits. Real diagnosis:

  • Missing 3 composite indices.
  • Connection pooling (PgBouncer) was sized for 5 concurrent connections; the client had 150 Django workers trying to open new connections.
  • WAL logs (write-ahead logging) went to slow disk instead of NVME.

Result: recalibrating those 3 things in 4 hours. 10x more throughput. Postgres was the right tool from the start.

The question then isn't "when does Postgres get slow" but "when does Postgres stop being sufficient for architectural reasons".


Postgres' Real Limits (When They Appear)

Postgres has genuine limits. Recognising this avoids pitfalls.

1. Distributed writes across multiple regions

Postgres replicates to standbys via WAL streaming. The standby can serve reads (read replicas). But writes only happen on the primary. For an application in Asia to write to a primary in Europe, latency is physics: minimum 150-300ms round-trip.

CockroachDB, YugaByte, Cassandra distribute writes. Each node can accept writes locally. The cost: eventual consistency or quorum writes (slower, but ACID per shard).

2. Write scaling without data splitting

Postgres scales writes vertically: CPU, RAM, more cores, better NVME. On a single server, there's a ceiling: ~150-200k TPS in pure write (pgbench test).

Distributed, write scales with number of shards. 10 shards = 10x throughput (with caveats: cross-shard queries are expensive; distributed transactions are very slow).

3. Maintenance without downtime windows

Replicating Postgres to standby and upgrading is smooth. But re-indexing, aggressive vacuum, or blocking schema changes still require locks. On critical applications, this marks maintenance windows.

Distributed (with correct configuration) allows rolling maintenance operations: one node exits, is updated, re-enters. Zero downtime.

4. Storage explosion on a single server

Postgres manages everything on one volume. 50GB is fine. 5TB starts becoming painful: snapshots become slow, WAL grows, recovery time is hours.

Distributed, data fragments. Each node holds 100GB; 50 nodes = 5TB distributed = fast snapshots, recovery in minutes.


Objective Criteria: When Migration Is a Real Technical Decision

Here's the uncomfortable truth: if you're reading this and counting that YES you have 3 of the 4 criteria below, migration makes sense. Otherwise, optimise Postgres.

Criterion 1: Sustained write throughput above 50k TPS

Not a spike. Baseline: 50k transactions per second, consistently, over 24h.

Test: run pgbench -c 100 -j 10 -T 300 on your current server. If you see p99 latency >100ms in stable load, and you've already increased CPU/RAM without improvement, this signals Postgres limit.

Criterion 2: Data needs to exist in 3+ regions with local writes, latency <200ms

Example: fintech with customers in US, EU, Asia. Each region needs to write locally (regulatory compliance). Latency between US <> Asia is 200-300ms. Postgres replicated to remote standbys creates a problem: writes always go to EU primary, latency is bad.

CockroachDB with configuration tuning (quorum reads, follower reads) solves this. YugaByte too, with tablet replication.

Criterion 3: SLA of 99.95%+ without planned maintenance windows

99.95% = ~21 minutes downtime/year. That's tight. Postgres with standby HA achieves 99.9%, but schema upgrades, re-indexing, or manual failover mark downtime.

Distributed with rolling operations, disable node, upgrade without affecting cluster. Zero downtime on maintenance.

Criterion 4: Query patterns are mainly aggregations on partitions; you don't need cross-partition JOINs

If your workload is "aggregate events by user_id" (partitioned), write-heavy, reads occasional, Cassandra is an option. But if you need JOINs between tables spread across different shards, distributed gets expensive (distributed query planning is complex; cross-shard JOINs require data collection from multiple nodes, network round-trips).

Postgres solves this in memory on one node. CockroachDB/YugaByte try but with overhead.

Practical test: do you have 2+ of these criteria? Diagram the migration. Do you have 1 or zero? Optimise Postgres.


Real Pitfalls in Migration

We've seen clients begin migration enthusiastically and discover late that the new system brought unexpected problems.

Pitfall 1: "Distributed transactions are ACID". Yes, but they cost 10x more latency.

CockroachDB guarantees ACID cross-shard. But to serialise writes across multiple partitions, it uses two-phase commit (2PC). Each network round-trip adds 50-100ms. A simple transaction in Postgres (1ms local) becomes 100-500ms distributed.

Applications that achieved 100ms p99 latency SLA in Postgres suffer culture shock: suddenly everything is 300ms+. They require rewrite: aggressive caching, local eventual consistency, async processing.

Pitfall 2: Connection pooling and distributed backpressure is hard.

Postgres + PgBouncer: you size 50 connection pool, limit is clear. Distributed? Each cluster node has a limit. Coordination is manual. Tools like ProxySQL/Vitess help but add an extra operational layer.

Pitfall 3: Hot data (hotspots) still gets slow.

If 80% of writes go to 1 partition (e.g. giant "enterprise" tenant), distribution doesn't help. That partition is the bottleneck. Postgres at least solves this in fast local RAM. Distributed, you have that partition replicated, but still network latency.

Pitfall 4: Queries written for Postgres aren't directly compatible.

LATERAL joins, RECURSIVE CTEs, WINDOW FUNCTIONS work in Postgres. CockroachDB/YugaByte support most, but edge cases exist. Migration testing is weeks, not days.


Concrete Alternatives (And When Each Makes Sense)

PostgreSQL with read replicas + connection pooling

Cost: €0-500/month on cloud (Heroku, Railway, Neon, Supabase).

Scale: up to 100k TPS on read-heavy; write scales to 50k TPS with tuning.

Best for: B2B SaaS with 80% reads, 20% writes pattern. Fintech, ecommerce, CRM.

When it falls short: multiregion with local writes, very large datasets (>10TB), or ultra-high write throughput.

CockroachDB

Cost: €1500+/month managed (Cockroach Cloud); self-hosted is free software but ~€50k/year in ops.

Scale: 100k+ TPS distributed, 99.99% uptime.

Best for: global multiregion with local writes, high SLAs, mixing OLTP + OLAP.

Issues: eventual consistency tuning is complex, network overhead is visible, enterprise licensing is expensive.

YugaByte

Cost: similar to CockroachDB.

Scale: 100k+ TPS, better support for Cassandra-like workloads (wide-column).

Best for: organisations already familiar with Cassandra; YCSB-style workloads.

Issues: smaller community than CockroachDB, less mature documentation.

Cassandra

Cost: free open-source, but ops is very difficult.

Scale: millions of TPS on append-only; terrible at updates/deletes.

Best for: time series, logging, immutable audit trails.

Issues: not a relational database; no ACID; no JOINs; simple queries are fast, but complex aggregations require application rewrite.


Practical Decision Process

Step 1: Measure the current state.

EXPLAIN ANALYZE on main queries. pg_stat_statements to find slow queries. vmstat, iostat to see if it's CPU, RAM, or I/O.

Step 2: Optimise Postgres before migrating.

Indices, connection pooling, WAL tuning, application work (batch inserts, prepared statements). 80% of cases resolve here.

Step 3: If still slow, diagram a new system.

Create POC in CockroachDB/YugaByte. Migrate 10% of data. Test real queries. Measure latency, throughput, consistency behaviour.

Step 4: If POC confirms gain (and costs justify it), plan migration in phases.

Blue-green with both systems running in parallel. Dual-write data sync during transition. Easy fallback if problems appear.


What We've Seen Work

An analytics SaaS platform started with Postgres, ~1M events/day on ingestion. Thought it was "ready for distributed". Real diagnosis:

  • Ingestion was async batch, but pooling had a limit. Event queue accumulated.
  • Aggregation queries went to COPY to S3 + separate Redshift. Postgres was only for "hot" data (7 days).
  • Rewrite: async ingestion with backpressure, Postgres + read replicas in 2 regions (US + EU), Redshift for history.

Result: 10x throughput, reduced latency, zero distributed migration. Postgres + well-thought ops solved 5 years of scaling.

The lesson: distribution is the right tool for 5-10% of problems. For the other 90%, it's application engineering and infra tuning.


Conclusion

Postgres is sufficient for most B2B SaaS applications until real architectural limits appear (multiregion with local writes, extreme write throughput, ultra-high SLAs, or datasets measured in tens of terabytes).

Migration is valuable when 2+ criteria coexist: throughput >>50k TPS, geographic distribution with local writes, 99.95%+ SLA, or query patterns that don't require cross-partition JOINs.

Before choosing to migrate, measure, optimise Postgres, test POC in a new candidate. 8 times in 10, you've solved the problem first time around.

If you're facing a similar problem and want a concrete diagram of your stack, book a conversation at https://impact-origin.com/agendamento.

Impact OriginEnjoyed this article?At Impact Origin we help founders and teams build and scale custom software, from a startup MVP to the next step. If you have a project in mind, let's talk.
Migrating from PostgreSQL to Distributed Database: When and How to Decide | Impact Origin