MongoDB vs MySQL
MySQL and MongoDB are two of the most widely used databases in the world, and they are often compared when starting a new project. MySQL is a relational database built on tables and SQL; MongoDB is a document database built on flexible JSON-like documents.
This tutorial compares them feature by feature, builds the same small feature in both, and ends with clear guidance on when each one is the better choice.
1. At a Glance
| Aspect | MySQL | MongoDB |
|---|---|---|
| Type | Relational (RDBMS) | Document (NoSQL) |
| Data stored as | Rows in tables | BSON documents in collections |
| Schema | Fixed, defined with CREATE TABLE | Flexible, optional JSON Schema validation |
| Query language | SQL | MongoDB Query API and aggregation pipeline |
| Relationships | Foreign keys and joins | Embedding, references and $lookup |
| Transactions | ACID (InnoDB engine) | Atomic single-document writes; multi-document ACID transactions |
| High availability | Replication, InnoDB Cluster / Group Replication | Replica sets with automatic failover |
| Horizontal scaling | Usually manual sharding or external tools | Built-in sharding |
| Current versions | MySQL 8.4 LTS and 9.x | MongoDB 8.0 |
| Managed cloud | Amazon RDS / Aurora, Azure, Google Cloud SQL, HeatWave | MongoDB Atlas |
2. Data Model
A blog with posts and tags shows the difference. In MySQL, a post's tags need a separate table because a column holds one value:
CREATE TABLE posts (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
author_id INT NOT NULL,
created_at DATETIME NOT NULL
);
CREATE TABLE post_tags (
post_id INT NOT NULL,
tag VARCHAR(50) NOT NULL,
PRIMARY KEY (post_id, tag),
FOREIGN KEY (post_id) REFERENCES posts(id)
);
In MongoDB, the tags are simply an array inside the post:
db.posts.insertOne({
title: "Indexing Strategies That Scale",
authorId: 7,
createdAt: new Date(),
tags: ["mongodb", "performance", "indexing"]
})
3. Queries Compared
| Task | MySQL | MongoDB |
|---|---|---|
| Find posts with a tag | SELECT p.* FROM posts p JOIN post_tags t ON t.post_id = p.id WHERE t.tag = 'mongodb' | db.posts.find({ tags: "mongodb" }) |
| Newest 10 posts | SELECT * FROM posts ORDER BY created_at DESC LIMIT 10 | db.posts.find().sort({ createdAt: -1 }).limit(10) |
| Count posts per author | SELECT author_id, COUNT(*) FROM posts GROUP BY author_id | db.posts.aggregate([{ $group: { _id: "$authorId", n: { $sum: 1 } } }]) |
| Add a field | ALTER TABLE posts ADD COLUMN views INT DEFAULT 0 | Just write it: db.posts.updateOne({…}, { $inc: { views: 1 } }) |
4. Joins and Relationships
MySQL is built for joins: data is normalized into many tables, and queries combine them freely. MongoDB can join collections with the $lookup aggregation stage, but a good MongoDB design embeds data that is read together, so most reads need no join at all.
db.posts.aggregate([
{ $match: { tags: "mongodb" } },
{ $lookup: { from: "authors", localField: "authorId", foreignField: "_id", as: "author" } },
{ $unwind: "$author" },
{ $project: { title: 1, "author.name": 1 } }
])
5. Transactions and Consistency
Both databases provide ACID transactions. In MySQL, transactions are part of everyday use with the InnoDB engine. In MongoDB, a write to one document is already atomic, including all its nested fields and arrays, so many operations that need a transaction in MySQL need none in MongoDB. For changes across documents, MongoDB offers multi-document transactions, even across shards.
6. Scaling and Availability
- MySQL typically scales by using a larger server and adding read replicas. Spreading writes across many servers needs application-level sharding or extra products such as Vitess.
- MongoDB includes replica sets for failover and sharding for horizontal write scaling. Adding a shard is an operational task, not an application rewrite.
7. Performance
Neither database is "faster" in general. Performance depends on how well the schema and indexes match the queries:
- MongoDB shines when the application loads or saves whole entities, such as a full order or user profile, in one operation.
- MySQL shines at queries that combine and aggregate many normalized tables in ways that were not planned in advance.
- Both need the right indexes. A missing index hurts either database far more than the choice of database does.
8. The Gap Is Narrowing
MySQL has a native JSON column type with functions to query inside it, and MongoDB has schema validation, transactions and joins. The difference lies in what each is designed around: MySQL treats JSON as one column type inside a relational world, while in MongoDB the document is the core of everything, including indexes, queries, replication and sharding.
9. When to Choose Which
| Choose MySQL when… | Choose MongoDB when… |
|---|---|
| Data is highly structured and relationships are central (accounting, inventory, ERP) | Records vary in structure or contain nested lists (catalogues, profiles, content) |
| You rely on complex ad-hoc SQL reporting | Access patterns are known and centred on entities |
| Your team and tools are SQL-centric | Your team works with JSON and object-oriented code |
| One server plus replicas covers the expected load | You expect to scale writes horizontally |
| An existing system or vendor requires a relational database | The data model changes often during development |
10. Summary
- MySQL stores rows in fixed tables and uses SQL and joins; MongoDB stores flexible documents and uses the MongoDB Query API.
- Both support ACID transactions; MongoDB's single-document atomicity removes the need for many of them.
- MongoDB has built-in sharding for horizontal scale; MySQL typically scales up and out with replicas.
- Choose based on data shape, query style, scale and team experience; using both is common and reasonable.