PostgreSQL vs MongoDB Real World: What Actually Happens

by Daniel Reeves

Most database arguments happen before anyone has written a single query. The team picks a side in a 45-minute architecture meeting, someone wins, and then six months later you're the one staring at a 3 AM PagerDuty alert wondering why you trusted that decision.

I've run both in production. PostgreSQL on a SaaS billing system that processed roughly 40,000 transactions a day. MongoDB (v6.0) on a content platform where the schema genuinely changed every few weeks because the product team couldn't make up their minds. Neither database is a villain. But the way they're marketed — Postgres as the boring reliable workhorse, Mongo as the flexible modern choice — papers over the real tradeoffs you'll hit once the honeymoon ends.

This piece is about those tradeoffs. The PostgreSQL vs MongoDB real world comparison that doesn't stop at "one is relational, one is document-based."

Where MongoDB's Flexibility Actually Helps

MongoDB's pitch is schema flexibility, and honestly, in one specific scenario, it's not wrong. If your data structure is genuinely unstable — think early-stage product, heavy experimentation, or ingesting third-party payloads you don't control — the ability to just write a document without migrating a table first is real relief.

On that content platform I mentioned, we were storing structured editorial metadata that varied wildly by content type. A video had different fields than a podcast, which had different fields than a long-form article. In Postgres we'd have ended up with either a rats-nest of nullable columns or a separate table per content type. In Mongo, we just wrote the document. It worked.

But here's where teams get burned: they assume this flexibility scales to all their data. It doesn't. The moment you need to query across documents — find me all content where author.id = 123 AND published_date > 2024-01-01 AND tags contains "fintech" — you're writing aggregation pipelines that look like someone tried to encode JSON inside BSON inside a fever dream. The query syntax is expressive but verbose, and it punishes you for not planning indexes early.

// MongoDB aggregation to find recent tagged content by author
db.content.aggregate([
  { $match: {
    "author.id": 123,
    "published_date": { $gt: new Date("2024-01-01") },
    "tags": { $in: ["fintech"] }
  }},
  { $sort: { published_date: -1 } },
  { $limit: 20 }
])

That's fine. But add two more conditions and a $lookup (Mongo's join equivalent), and you'll wish you'd just written SQL.

Where PostgreSQL Earns Its Reputation

Postgres is 35 years old. That's not a knock — it's a reason to trust it. The query planner is genuinely good. EXPLAIN ANALYZE gives you legible output. The extension ecosystem (PostGIS for geo, pgvector for embeddings, TimescaleDB for time-series) means you can push a surprising amount of specialised work into the same database rather than spinning up another service.

The billing system I ran on Postgres handled multi-currency transactions with complex proration logic. The schema had 22 tables. The foreign key constraints alone caught three bugs in the first month that would have silently corrupted data in a document store. That's not theoretical — that's a constraint violation error at write time instead of a confused support ticket two weeks later.

-- Postgres: enforce referential integrity at the DB layer
ALTER TABLE invoices
  ADD CONSTRAINT fk_customer
  FOREIGN KEY (customer_id)
  REFERENCES customers(id)
  ON DELETE RESTRICT;

You can't do that in MongoDB without application-level enforcement, which means you're trusting every service that touches that collection to behave. In a monolith with one team, maybe fine. In a microservices setup with four teams? Good luck.

Postgres also has JSONB. I know, I know — it feels like cheating to mention it in a Postgres vs MongoDB comparison. But if your argument for Mongo is "I need flexible document storage," Postgres has had production-grade JSONB since version 9.4 (2014). You can index into it, query it with operators, and still keep the rest of your schema relational. It's not as ergonomic as Mongo's native document model, but it closes the gap considerably.

The Operational Reality Nobody Talks About

Both databases will hurt you operationally, just in different ways.

MongoDB's replica sets are easier to set up than Postgres streaming replication, and Atlas (their managed cloud offering) genuinely abstracts away a lot of pain. If you're a small team without a dedicated DBA, Atlas at the M10 tier (~$57/month as of mid-2024) is a reasonable starting point. But Atlas locks you into their pricing curve fast, and the free tier (M0) is so limited — 512MB storage, shared cluster — that it's barely useful for anything beyond a toy project.

Postgres on RDS or Aurora is similarly managed, but the mental model for replication, WAL archiving, and point-in-time recovery is more exposed. You'll need to understand it eventually. The upside is that the community documentation is exceptional. The Postgres mailing list archives have answers to questions you haven't thought of yet.

One operational gotcha specific to MongoDB: the WiredTiger storage engine's cache behavior can surprise you. By default it uses 50% of available RAM minus 1GB. On a server with 4GB RAM, that's 1.5GB of cache. If your working set exceeds that, you'll see disk I/O spikes that look like mysterious slowdowns. Tuning wiredTigerCacheSizeGB in mongod.conf is the fix, but you have to know to look for it.

Comparing the Two Directly

Dimension PostgreSQL MongoDB
Schema flexibility Rigid (JSONB helps at edges) Native document model
Query language SQL — mature, portable MQL / aggregation pipeline — expressive but verbose
Joins First-class, optimized $lookup — works, but costly at scale
Transactions Full ACID since forever Multi-document ACID since v4.0 (2018)
Horizontal scaling Harder (Citus, partitioning) Built-in sharding
Managed cloud cost RDS/Aurora — predictable Atlas — can escalate quickly
Ecosystem maturity 35 years, enormous ~15 years, growing
Best fit Relational, financial, complex queries Document-heavy, variable schema, rapid iteration

MongoDB added multi-document ACID transactions in v4.0, which closed the biggest legitimate criticism. But there's a performance cost — transactions in Mongo are slower than in Postgres, and the driver ergonomics for using them correctly are clunkier than you'd hope.

When I'd Pick Each One

Here's where I'll stop hedging.

I'd pick PostgreSQL for anything involving money, user accounts, inventory, or any domain where data integrity is non-negotiable. I'd also pick it for any project where I expect complex reporting queries — SQL is simply better for that than aggregation pipelines. And I'd pick it if the team already knows SQL, because the learning curve for Postgres is almost flat if you do.

I'd pick MongoDB if I was building something where the schema was genuinely unknown — an early product, a data ingestion pipeline handling heterogeneous third-party payloads, or a content system with highly variable document shapes. I'd also consider it if horizontal write scaling was a hard requirement from day one, though honestly, most applications don't hit that wall before they've had time to reconsider.

What I wouldn't do is pick MongoDB because it feels more modern, or because someone on the team watched a conference talk about microservices. That's how you end up with a document store full of documents that are all exactly the same shape, which is just a relational table with worse tooling.

The Real World Verdict

The PostgreSQL vs MongoDB real world comparison comes down to this: Postgres makes you think harder upfront and rewards you later. MongoDB lets you move fast early and asks for payment later — in query complexity, in operational tuning, in the moment you realize you need a join.

Neither is universally better. But most applications are more relational than their architects initially admit. If you're unsure, start with Postgres. You can always migrate toward document storage for specific collections using JSONB or a separate service. Going the other direction — realizing you needed relational integrity after the fact — is a much harder conversation.

Tomorrow: open your current project's data model and ask yourself honestly how many of your MongoDB collections have a fixed, predictable shape. If the answer is "most of them," you already know what to do.