← All posts
Aug 24, 2025 · 7 min read

PostgreSQL vs MongoDB: how to actually choose

Not "SQL vs NoSQL". The real question is whether your data has a fixed shape and how much you care about relationships. Here is a simple way to decide.

PostgreSQLMongoDBDatabasesBeginner

This is the question I got asked most as a junior, and the answers online are usually useless — "Mongo is for unstructured data", "Postgres is for relations". Technically true, practically unhelpful.

Let me try to explain it the way I wish someone had explained it to me.

Step 1: How each one stores your data

PostgreSQL stores rows in tables

You define the shape first. Every row must match it.

CREATE TABLE users (
  id       SERIAL PRIMARY KEY,
  email    TEXT NOT NULL UNIQUE,
  name     TEXT NOT NULL,
  created  TIMESTAMP DEFAULT now()
);

If you try to insert a user without an email, the database rejects it. The rules live in the database, not in your code.

MongoDB stores documents in collections

A document is basically JSON. There is no fixed shape unless you add one.

{
  "_id": "65f...",
  "email": "nikhil@example.com",
  "name": "Nikhil",
  "address": { "city": "Indore", "country": "India" },
  "tags": ["backend", "node"]
}

Notice the nested object and the array. In Postgres those would normally be two extra tables. In Mongo they sit inside the same document.

Step 2: The question that actually decides it

Forget "structured vs unstructured". Ask this instead:

When I read this data, do I usually need it all together, or do I need to combine it with other things in ways I cannot predict?

That is the whole decision.

Step 3: Things that surprise people

"Mongo is faster"

Only for the shape it likes — fetching one whole document by id. Once you start doing $lookup (Mongo's version of a join) across three collections, Postgres will usually beat it. And a Postgres query on a properly indexed table is extremely fast.

In practice, the thing that made my APIs slow was never the database engine. It was missing indexes. I improved API performance by about 40% at one job almost entirely by adding the right indexes and fixing N+1 queries — same database, same hardware.

"Postgres cannot do JSON"

It can, and well. The JSONB column type stores real JSON, you can index inside it, and you can query nested fields:

SELECT * FROM events
WHERE payload->>'type' = 'order_filled';

So "I have some flexible fields" is not a reason to pick Mongo any more. You can have a strict table with one flexible JSONB column. I do this often — it is the best of both.

"Schemaless means no schema"

It does not. Your data still has a shape — the shape just lives in your application code now, spread across every file that touches that collection. Six months in, you will find documents from three different eras of your app sitting in the same collection, and nothing stopped that from happening. Mongoose schemas help, but they are enforced by your app, not the database.

Step 4: A simple decision list

Pick PostgreSQL when

Pick MongoDB when

Step 5: My honest default

If I am unsure, I start with PostgreSQL. Not because Mongo is bad — I have used it heavily and it is genuinely good at what it is good at. But an unsure project is one where requirements will change, and changing requirements usually mean new relationships and new queries you did not plan for. Postgres handles that better, and JSONB covers the flexible parts.

The reverse mistake is more painful. Rebuilding relational logic on top of a document store — joins in application code, manual consistency between collections — is a lot of work you did not need to do.

Short version: if your data is a graph of related things you will query in changing ways, use Postgres. If it is a pile of independent documents you read whole, use Mongo. When unsure, Postgres with a JSONB column.

← All posts Questions? Get in touch →