PostgreSQL and MongoDB are both capable. The choice usually comes down to data shape, query patterns, team experience, and how much you care about schema and relations. Here’s how I decide.
What Each Gives You
PostgreSQL — Relational model: tables, rows, foreign keys, ACID transactions, and SQL. Strong for structured data, joins, and reporting. Schema is explicit (migrations); you get constraints, indexes, and a mature ecosystem (PostGIS, extensions). Fits when your domain has clear entities and relationships.
MongoDB — Document model: collections and JSON-like documents. Flexible schema; you can evolve documents over time without formal migrations. Good for nested, variable-shaped data (e.g. profiles with optional fields, event payloads). Denormalization is common; you design documents for how you read them. Horizontal scaling and sharding are first-class.
When I Choose PostgreSQL
- Structured domain with clear relations — Users, orders, products, roles, permissions. When the data is naturally tabular and you need joins (e.g. “orders with customer and line items”), PostgreSQL is a natural fit. Normalized schema reduces duplication and keeps consistency.
- Transactions and consistency — When a single operation must update several rows or tables atomically (e.g. debit one account, credit another), relational DBs and transactions are what you want. PostgreSQL’s transaction model is well understood and robust.
- Reporting and analytics — SQL is built for aggregations, filters, and reporting. When the product or stakeholders need “list X by Y, sum Z, group by W,” PostgreSQL (and tools that speak SQL) make this straightforward.
- Team knows SQL and relational design — Many backends and agencies are comfortable with tables, migrations, and ORMs (Prisma, TypeORM, etc.). PostgreSQL fits that skillset and has great tooling (Supabase, Neon, etc.).
- Nest.js or type-first backends — Nest.js and TypeScript pair well with Prisma/TypeORM and PostgreSQL. You get types from schema, migrations, and a clear data model. I default to PostgreSQL for new Nest.js APIs unless the data is clearly document-shaped.
When I Choose MongoDB
- Document-shaped or variable structure — Content with optional fields, user-generated forms, or events where each document can have different attributes. When the schema varies by document or changes often, MongoDB’s flexibility can reduce migration churn.
- Nested data read as a unit — When you often load “one thing and everything inside it” (e.g. a project with tasks and comments embedded or in sub-docs), documents can match that read pattern. You avoid joins at the cost of some duplication and careful design to avoid huge documents.
- Team prefers document APIs — Some teams are more productive with documents and aggregation pipelines than with SQL. When that’s the case and the data fits, MongoDB is a good fit.
- Already in the stack — If the project or client already uses MongoDB and the data is working, we don’t switch to Postgres without a strong reason (e.g. need for complex joins or reporting that’s painful in Mongo).
The “Hybrid” Option
Sometimes we use both: PostgreSQL for core transactional data (users, billing, orders) and MongoDB (or another store) for logs, events, or flexible content. Not every app needs that—but when one part of the system is clearly relational and another is clearly document/event-based, splitting can make sense.
What I Don’t Do
- Don’t pick MongoDB to avoid schema — You still need to think about indexes, document shape, and how you’ll query. “Schema-less” doesn’t mean “no design.” Bad document design leads to slow queries and messy code.
- Don’t pick PostgreSQL only because “relational is correct” — For highly variable or nested data that’s always read as a whole, documents can be simpler. Choose by data shape and access patterns, not ideology.
- Don’t migrate without a clear problem — If the current database is working, we don’t switch to the other just to try it. We switch when we hit real limits (e.g. reporting in Mongo is painful, or we need strict relations and transactions in a doc store).
In short: I default to PostgreSQL for most backends—structured data, relations, transactions, and reporting. I choose MongoDB when the data is document-shaped, variable, or read as a unit, and when the team and stack align with it. Both are production-ready; pick by domain shape, query patterns, and team.
Saad Mehmood — Portfolio
Top comments (0)