Learning objectives
After reading this article you will be able to:
- Understand how the document model and the relational model differ
- Compare joins, transactions, JSON and indexes with working examples
- Choose between MongoDB and PostgreSQL for your type of project
MongoDB and PostgreSQL are two of the most popular databases for web apps, APIs and bots. Both store and query your data, but with different models. PostgreSQL keeps data in tables with a fixed schema and links them with joins. MongoDB stores JSON-like documents in collections.
The right choice depends on the shape of your data and how you read it, and the sections below compare the two point by point, with code. If you are still choosing between database families, start with which database to choose.
What is each one?#
PostgreSQL is an open-source relational database. You define tables with typed columns, and queries use SQL. Rows in different tables connect through foreign keys. See what is PostgreSQL for the basics.
MongoDB is a document database. A record is a BSON document (a binary form of JSON) with nested objects and arrays, and documents live in collections that do not force a fixed schema. Queries use MongoDB's own API and aggregation pipeline, not SQL. See what is MongoDB.
How do they differ at a glance?#
| Criterion | PostgreSQL | MongoDB |
|---|---|---|
| Model | Tables, rows, columns | Collections of documents |
| Schema | Defined up front, enforced by the database | Flexible by default |
| Query language | SQL | MongoDB API and aggregation pipeline |
| Relations | Foreign keys and JOIN |
Embedding, or $lookup in aggregation |
| Transactions | ACID, the normal way to work | ACID across documents, with extra cost |
| JSON | jsonb column, GIN-indexable |
Native format |
| Size limit | 1 GB per field | 16 MiB per document |
| Scaling out | Read replicas, partitioning | Replica sets and built-in sharding |
How does the data model change your design?#
Take an order with a customer and two items. In MongoDB you usually embed everything in one document:
{
_id: "ord_1001",
customer: { name: "Ana", email: "ana@example.com" },
items: [
{ sku: "A-1", qty: 2, price: 19.9 },
{ sku: "B-7", qty: 1, price: 49.0 }
],
status: "paid"
}One read returns the whole order. The MongoDB documentation recommends embedding data that is read together. The cost is duplication: if the customer's email changes, every order that embedded it keeps the old value unless you update them all.
In PostgreSQL you split the same data into related tables:
CREATE TABLE customers (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name text NOT NULL,
email text NOT NULL UNIQUE
);
CREATE TABLE orders (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
customer_id bigint NOT NULL REFERENCES customers (id),
status text NOT NULL
);
CREATE TABLE order_items (
order_id bigint NOT NULL REFERENCES orders (id),
sku text NOT NULL,
qty int NOT NULL CHECK (qty > 0),
price numeric(10,2) NOT NULL
);The email lives in one place, and the database rejects an order for a customer that does not exist. Reading a full order takes a join, which is cheap when the foreign key columns are indexed.
How do joins and relations work?#
In PostgreSQL, joins are the core of the language:
SELECT o.id, c.name, i.sku, i.qty
FROM orders o
JOIN customers c ON c.id = o.customer_id
JOIN order_items i ON i.order_id = o.id
WHERE o.status = 'paid';MongoDB can join too. The $lookup stage performs a left outer join with a collection in the same database:
db.orders.aggregate([
{ $match: { status: "paid" } },
{ $lookup: {
from: "customers",
localField: "customerId",
foreignField: "_id",
as: "customer"
} }
]);It works, but it is the exception in a MongoDB design, not the default. If most of your queries need data from three or four collections at once, you are fighting the model, and PostgreSQL will feel more natural.
How do transactions compare?#
PostgreSQL is built around transactions: every statement runs in one, and BEGIN ... COMMIT groups several. Even ALTER TABLE can run inside a transaction.
MongoDB makes a write to a single document atomic, including its nested objects and arrays. It also supports multi-document ACID transactions on replica sets and sharded clusters. They do have limits: a transaction must finish within 60 seconds by default (the transactionLifetimeLimitSeconds setting), and long transactions put pressure on the storage cache. The documentation tells you to keep transactions short and to model data so most operations touch one document.
For money movements, stock counts or anything where two records must change together, PostgreSQL makes the safe path the default.
How do they handle JSON?#
PostgreSQL stores JSON in a jsonb column and can index it with GIN:
CREATE TABLE events (id bigserial PRIMARY KEY, payload jsonb NOT NULL);
CREATE INDEX events_payload_gin ON events USING GIN (payload);
SELECT id FROM events WHERE payload @> '{"type": "signup"}';This hybrid is a good middle ground: regular columns for the stable fields, and one jsonb column for the part that varies. The PostgreSQL documentation recommends jsonb over json for most applications. What you give up is the tooling MongoDB built for documents, such as its aggregation pipeline.
In MongoDB the same query is native:
db.events.find({ type: "signup" });How do they scale?#
For most projects the first limit you hit is a missing index or too little RAM, not the engine. Fix those first.
Past that point the approaches differ. PostgreSQL usually scales up first (more RAM and CPU), then adds read replicas and table partitioning. MongoDB has built-in sharding: it splits a collection across servers by a shard key. That helps with very large datasets, but the shard key is a design decision you need to make early. For the terms, see collections, clusters and replica sets.
When should you pick each one?#
Pick PostgreSQL if your data is highly related (users, orders, payments), you need constraints and joins, you report on data with SQL, or you want one general-purpose database as the default for a new project.
Pick MongoDB if records are self-contained and vary in shape (catalogs with different attributes, content, event logs, profiles), you read them whole, and your team already works with JSON objects in Node.js.
If you are still unsure, go with PostgreSQL for relational data and add jsonb where you need flexibility. Switching later is possible but costs real work. For a comparison inside the SQL family, see PostgreSQL vs MySQL.
How to do this on Square Cloud#
Square Cloud offers MongoDB and PostgreSQL hosting from the Standard plan, along with MySQL and Redis. The Hobby plan does not include database hosting.
You create the database in the dashboard, always on a recent version, and it is provisioned in seconds in the same datacenter as your applications (about 1 ms average latency), with mandatory TLS. Both run as a single node (standalone), so MongoDB has no replica set. PostgreSQL is native PostgreSQL, without extensions. You pick the engine, connect your application with the connection URL the dashboard gives you and control the rest.
You take manual snapshots whenever you want, and every plan that includes databases also has an automatic daily snapshot. You can restore a snapshot into the same database, another one of the same engine or a new database. Both engines can live on the same plan, each using at least 1024 MB of the plan's RAM, so you can test the comparison above on your own data before committing.
See database hosting, MongoDB hosting and PostgreSQL hosting.
Database hosting
MongoDB, PostgreSQL, MySQL and Redis next to your app
FAQs
Is MongoDB faster than PostgreSQL?
Neither is faster across the board: speed depends on the data model, the indexes and the query. MongoDB is fast at reading a whole document by key, and PostgreSQL at joins and aggregations over related tables. Test with your own data.
Does MongoDB support transactions like PostgreSQL?
Yes. MongoDB supports multi-document ACID transactions on replica sets and sharded clusters. They cost more than single-document writes, so the documentation recommends modeling data so most operations touch one document.
Can PostgreSQL store JSON like MongoDB?
Yes. The jsonb type stores JSON in a binary format and can be indexed with GIN. You still get SQL, joins and constraints on the rest of the data, but you do not get MongoDB's aggregation pipeline.
Can I migrate from MongoDB to PostgreSQL later?
Yes, but plan for work. You have to design tables, decide what stays in jsonb, rewrite queries from the aggregation pipeline to SQL and move the data. Choosing well early is cheaper.
Which is better for a beginner?
PostgreSQL gives you SQL, a skill that transfers to MySQL and most other databases. MongoDB is quick to start if you already think in JSON objects. Both have good official drivers for Node.js and Python.
More in Databases
See all 24 articles- How much does database hosting cost?Cloud database hosting costs from zero to hundreds of dollars a month. See what sets the price: instance, disk, traffic, snapshots, and how to estimate yours.
- How to host a database for your appTo host a database, pick an engine, create the instance, store the connection string in an environment variable and test the connection. Step-by-step guide.
- What is Redis used for?Redis is an in-memory data store that keeps key-value pairs and rich data structures. Learn how it works, what it is used for and when not to use it.
- How to back up your databaseBack up MySQL, PostgreSQL and MongoDB with mysqldump, pg_dump and mongodump, then restore the dump. See the commands, how to verify and common mistakes.