Build the mental model
A relational database stores data in strictly-typed tables with a fixed schema, and uses foreign keys plus JOIN operations to stitch related tables together at query time — this makes it excellent when your data has many relationships (orders link to users link to products) and you need ACID transactions, meaning a multi-step write either fully succeeds or fully rolls back, leaving no half-finished state even under concurrent access or crashes. NoSQL databases (document stores like MongoDB, key-value stores like Redis, wide-column stores like Cassandra) drop the fixed schema and often the JOIN entirely, letting each record shape itself independently and letting you scale writes horizontally across many cheap machines — the trade-off, formalized by the CAP theorem, is that under a network partition you typically sacrifice some consistency to keep the system available. The real decision framework is not 'NoSQL is web-scale, SQL is legacy' — it's asking what your access pattern needs: heavy relational joins and strong consistency point to SQL; flexible, rapidly-changing schemas or massive write throughput point to NoSQL.
Connect it to a real scenario
The Tutorial Platform's core relational data — users, courses, lessons, enrollments — has strong relationships (a user enrolls in many courses, a course has many lessons) and needs ACID guarantees (a payment and an enrollment record must both succeed or both fail), so it lives in a SQL database. But learner activity events — video watch progress, quiz attempts, page views used for analytics — arrive at huge volume with a loosely-defined, evolving shape, and don't need cross-record joins, making them a natural fit for a NoSQL document or wide-column store instead. Picking per-workload, not platform-wide, is the real skill.
Try the working example
SQL (Relational) NoSQL (Document Store)
+------------------+ +--------------------------+
| users | | { "_id": "u1", |
| id | name | | "name": "Aye", |
+----+-------------+ | "courses": [ |
| 1 | Aye | | { "title": "Rust", |
+------------------+ | "progress": 40 }, |
| FK | { "title": "Go", |
v | "progress": 10 } |
+------------------+ | ] |
| enrollments | | } |
| user_id | course | <-- JOIN needed +--------------------------+
+---------+---------+ Naturally good at:
| 1 | Rust | - flexible/evolving shape
+------------------+ - horizontal write scale
Naturally good at: - fast writes at huge volume
- multi-table relationships Weaker at:
- strong consistency (ACID) - cross-record joins
- complex queries across entities - strict schema enforcementThe comparison shows SQL trades flexibility for strong relational consistency, while NoSQL trades joins/strict schema for flexibility and write scale.5-minute try-it
Suppose the Tutorial Platform adds a comment feature — comments attach to a lesson and can have reply threads. Sketch how you'd model this in SQL versus NoSQL, and justify your pick.
One important caution
Assuming NoSQL is 'faster' and stuffing relationship-heavy data into a document store, then ending up re-implementing joins manually in application code.
Fearing SQL schema migrations and dumping many columns into a JSON blob column, losing the relational database's query optimization entirely.
Wikipedia — NoSQL — System Design