There is no single best database. Learn a decision framework for picking the right store per workload, and how real systems combine several — polyglot persistence — behind one application.
Choosing a database is a matter of matching the workload — access patterns, scale, consistency needs, data shape — to a store’s strengths, not following fashion. Start from the questions you must answer and the guarantees you need, then eliminate. Often the answer is still a relational database; NoSQL earns its place only where a specific pressure (scale, shape, connectedness) makes relational the wrong fit.
Pick by workload, not hype. Ask in order:
1. Access pattern? key lookup -> KV; query-any-field -> document;
by-partition-over-time -> wide-column;
traverse relationships -> graph;
ad-hoc joins + transactions -> RELATIONAL
2. Scale? single-node fine -> relational; write firehose -> wide-column
3. Consistency? must-be-correct-now -> CP/relational; always-up -> AP
4. Data shape? tabular -> relational; nested -> document; connected -> graph
Default to a relational DB. Choose NoSQL when a SPECIFIC pressure makes
relational the wrong fit — not because NoSQL is "modern".Real systems rarely use one database — they use the right store for each job, a pattern called polyglot persistence. An e-commerce app might keep orders in PostgreSQL (transactions), sessions in Redis (speed), the product catalog in MongoDB (flexible), recommendations in Neo4j (graph), and analytics in a warehouse. The data engineer’s job includes moving and reconciling data across these stores.
One e-commerce system, several stores — each for what it's best at:
orders + payments PostgreSQL ACID transactions, correctness
sessions + cart Redis sub-ms reads, TTLs
product catalog MongoDB flexible, nested, evolving schema
recommendations Neo4j relationship traversal
event stream Cassandra massive write throughput
analytics Snowflake/BQ columnar aggregation (warehouse)
This is POLYGLOT PERSISTENCE. The data engineer moves + reconciles data
between them (CDC, pipelines) — and that plumbing is much of the job.Polyglot persistence is powerful but not free: every additional store is more operational burden, more ways for data to disagree, and more integration to build and keep in sync. The discipline is to add a specialized store only when its benefit clearly outweighs that cost, and to design the synchronization (often change data capture) deliberately rather than letting copies drift.
Every extra database has a cost:
operational another system to run, back up, secure, monitor, upgrade
consistency the same fact in two stores can DISAGREE (sync lag)
integration pipelines/CDC to keep them in sync = more to build + break
expertise the team must know each store's failure modes
So: add a specialized store only when its win clearly beats the cost.
Two well-run databases usually beat five half-understood ones. And design
the SYNC (change data capture, pipelines) on purpose — don't let copies drift.When the same data lives in several places, you need a reliable way to propagate changes — Change Data Capture streams every insert/update/delete from a source database (usually via its transaction log) to downstream stores and the warehouse. CDC is how a system stays polyglot without going inconsistent, and building these flows is squarely the data engineer’s responsibility, tying this course back to pipelines and streaming.
Change Data Capture (CDC): stream every change from a source to others.
PostgreSQL (source of truth)
| read the transaction log (WAL) — every insert/update/delete
v (Debezium -> Kafka)
+--> search index (Elasticsearch) keep search fresh
+--> cache (Redis) invalidate/refresh
+--> warehouse (Snowflake) analytics copy
CDC keeps a polyglot system consistent WITHOUT dual-writes from the app
(which drift + fail partially). Building CDC + these pipelines is core
data engineering — see the Data Engineering + Spark (streaming) courses.