Component Architecture · Phase 2: Core Infrastructure
SQL vs. NoSQL & Data Model Selection
A decision framework for selecting between Relational (Postgres), Key-Value (Redis), Document (Mongo), Wide-Column (Cassandra), Columnar/OLAP (ClickHouse), and Graph (Neo4j).
Primary specification: Designing Data-Intensive Applications: Chapter 2 - Data Models and Query Languages
Lesson 14 of 33
1d streakThe Architectural Question
Running large analytical aggregation queries on an OLTP primary competes with checkout for CPU, I/O, memory, cache residency, and database connections.
Core Engineering Objectives
- Access-pattern-first data modeling vs generalized normalization (3NF)
- Relational join flexibility vs denormalized distributed scale
- OLTP row stores vs OLAP columnar storage (ClickHouse/Snowflake) for analytical aggregations
Choose a data model from invariants and access patterns
SQL and NoSQL are broad families, not opposing performance modes. Start with the invariants that must hold, the reads and writes the product performs, the query shapes that may evolve, the required availability, and the operational skills of the team. Only then choose a database family and a specific product.
| Workload need | Often a strong starting point | Reason |
|---|---|---|
| Multi-row business invariants and evolving queries | Relational SQL database | Transactions, constraints, joins, and flexible indexes |
| Simple lookup by stable key at very high scale | Key-value store | Bounded access path and straightforward partitioning |
| Aggregate-shaped records retrieved together | Document store | Nested data can follow the application read shape |
| Large sparse datasets queried by known partition keys | Wide-column store | Partition-oriented writes and predictable range access |
| Large analytical scans and aggregations | Columnar analytical store | Column pruning and compressed vectorized processing |
Separate logical guarantees from physical scaling
Architectural Boundary · Do Not Confuse
Relational model: normalized relations, declared constraints, transactions, and a general query language.
Access-pattern model: denormalized records designed around a bounded set of partition-key queries.
Either family may replicate, shard, cache, or offer multiple consistency levels. The useful comparison is the guarantee and query contract of the selected system, not the label alone.
- 01Write down the invariants, such as an order total matching its line items or inventory never dropping below zero.
- 02List the highest-volume and latency-sensitive queries, including their partition or tenant boundaries.
- 03Estimate data size, write rate, read rate, hot keys, retention, and growth instead of choosing from current traffic alone.
- 04Decide which operations require one atomic transaction and which can tolerate asynchronous reconciliation.
- 05Evaluate operational requirements: backup, restore, schema evolution, observability, regional placement, and team experience.
R + W > N is not a complete strong-consistency proof
Turn business rules into storage invariants before naming a database
For checkout, useful invariants include “every order line references a valid product,” “a payment attempt is recorded once per idempotency key,” and “confirmed inventory never becomes negative.” A relational database can enforce some of these with keys, constraints, and transactions. A partitioned key-value design may instead keep one invariant inside a single item or partition and coordinate cross-partition work with a workflow.
Invariant: confirmed_stock >= 0
Command: reserve(product_id, quantity, idempotency_key)
Atomic boundary: one product partition
Read path: lookup reservation by idempotency_key
Failure rule: timeout means UNKNOWN; retry with the same key
Reconciliation: compare reservation events with payment outcomesSystem of record
The authoritative state against which derived views and recovery are reconciled.
Atomic boundary
The set of state changes that either commit together or do not commit.
Derived view
A search, cache, analytics, or read model rebuilt from authoritative changes.
Exhaust the simple relational scaling path before adding data systems
- 01Measure the slow query and inspect its plan; remove accidental full scans and N+1 access before changing database families.
- 02Add an index whose leading columns match the filter and ordering, while accounting for extra write and storage cost.
- 03Bound connection concurrency with a pool and reject or queue overload before the database thrashes.
- 04Cache stable hot reads when staleness is acceptable, and move non-interactive reporting away from the transactional primary.
- 05Use read replicas only for reads that tolerate replication lag; never silently route read-after-write invariants to a stale replica.
- 06Partition when size, maintenance, or write contention has a measured boundary and the partition key matches dominant access paths.
| Technique | It helps when | It does not fix |
|---|---|---|
| Indexing | Queries filter or order by predictable columns | Unbounded result sets or a saturated write path |
| Read replica | Many stale-tolerant reads dominate | Primary writes or strict read-after-write |
| Partitioning | Data and traffic have a useful ownership key | Cross-partition invariants and skewed hot keys |
| Vertical scaling | The workload still fits one larger failure domain | Unlimited growth or a poor query plan |
Compare concrete guarantees, not SQL and NoSQL stereotypes
| Question | What to verify in a candidate database |
|---|---|
| Transaction scope | single row, document, partition, shard, or arbitrary records |
| Read guarantee | eventual, monotonic, read-your-writes, snapshot, serializable, linearizable |
| Conflict behavior | leader coordination, conditional write, version merge, last-write-wins |
| Partition response | which operations reject, wait, or accept divergent state |
| Index guarantee | synchronous or asynchronous maintenance; local or global scope |
| Recovery guarantee | backup consistency, point-in-time restore, replay and reconciliation |
Modern products blur family labels: relational systems can shard and replicate; document stores can support multi-record transactions; key-value systems can offer conditional writes; distributed SQL systems can provide a relational model across nodes. Read the exact guarantee for the exact operation and topology you will deploy.
Schema flexibility moves validation; it does not remove it
Design the OLTP-to-analytics boundary as a recoverable pipeline
A large analytical scan does not automatically lock an entire MVCC table. The more common production failure is resource interference: scans consume CPU, I/O bandwidth, buffer-cache space, memory, and connections needed by short transactions. A separate analytical store isolates that workload, but the data pipeline becomes another distributed system.
- 01Commit the business transaction and its outbox record atomically in the system of record.
- 02Publish the change with a stable event ID and source position so consumers can deduplicate and resume.
- 03Apply idempotent transformations to the analytical model; preserve the source timestamp and ingestion timestamp.
- 04Measure end-to-end freshness lag, rejected records, schema-version failures, and source-to-sink count differences.
- 05Retain enough source history or snapshots to rebuild the analytical view after corruption or a transformation bug.
Active Recall Checkpoint
What new correctness problem appears when a dashboard moves from the OLTP database to an asynchronously updated analytical store?
Hint: The read no longer observes the transaction directly.
Show answer & explanation
The dashboard becomes a lagging derived view. The product must define an acceptable freshness target, expose or account for lag, make ingestion idempotent, monitor missing or rejected events, and retain a replay or rebuild path. Isolation protects checkout only if the pipeline itself is operable.
Use multiple stores only when the boundary earns its cost
A common production design keeps orders and payments in a relational system, publishes committed changes through an outbox or change-data-capture stream, and builds a separate search or analytical view. This is useful when the second access pattern cannot be served safely and economically by the primary store. It also creates lag, replay, monitoring, backup, and incident-response obligations.
Use it when
Begin with a relational database when correctness spans related records or future query shapes are uncertain. Choose a specialized store when a measured access pattern, scale boundary, or availability requirement clearly justifies it.
Reconsider when
Avoid polyglot persistence when one well-operated database can meet the workload. Every additional store adds data synchronization, recovery, expertise, and ownership costs.
Active Recall Checkpoint
A product needs transactional checkout and a dashboard that scans billions of events. Should both workloads query the checkout database?
Hint: Separate the system of record from the analytical access path.
Show answer & explanation
Keep checkout invariants in the transactional system of record. Publish committed changes to a columnar analytical store through a durable CDC or outbox pipeline, accept and measure the dashboard lag, and reconcile pipeline failures. This prevents large scans from consuming checkout connections and I/O.
Architectural Trade-Off Analysis
Compare latency, throughput, consistency, and operational complexity across core industry alternatives.
Architecture Decision Matrix
Multi-axis engineering evaluation and FAANG interview rules of thumb.
SQL (Postgres / MySQL)
Relational ACID Store
Structured schema, relational joins, ACID transactions, and strict foreign keys.
NoSQL (Cassandra / DynamoDB)
Distributed Non-Relational Store
Horizontal partition keys, denormalized documents/wide-columns, and tunable consistency.
| Evaluation Axis | SQL (Postgres / MySQL) | NoSQL (Cassandra / DynamoDB) | Details |
|---|---|---|---|
Latency | Moderate | Strong | |
Throughput | Moderate | Strong | |
Scalability | Moderate | Strong | |
Consistency | Strong | Moderate | |
Complexity | Strong | Moderate | |
Cost | Moderate | Strong |
When to Choose in an Architecture Interview
Choose SQL when ACID guarantees are non-negotiable (financial ledgers, payment processing, inventory checkout) or when query access patterns are unpredictable and require ad-hoc analytical joins.
Choose NoSQL when write volume exceeds single-node capacity (>20K writes/sec), data is unstructured/hierarchical (logs, telemetry, user feeds), or multi-region active-active replication is mandatory.
Never say "NoSQL is faster than SQL" without qualification. SQL with proper B-Tree indexes on indexed primary keys is lightning fast. NoSQL wins on horizontal write scaling, not inherent single-row read speed.
Production Postmortem & Verification
Production Incident Postmortem
- Trigger / Setup: Marketing dashboard queries analytics directly against production MySQL database during peak sales hours.
- Production Symptom: Long-running scans saturate I/O and the connection pool, evict hot pages, and starve short checkout transactions.
- Root Cause & Fix: Separate transactional OLTP workloads from analytical OLAP workloads; stream data via CDC to a columnar datastore.
Acceptance Criteria & Outcomes
- Formulate a decision matrix mapping read/write volume, schema stability, and query complexity to database families.
- Explain how column pruning, compression, and vectorized execution can reduce analytical scan work, then require workload-specific benchmarks.
- Demonstrate denormalized data modeling in wide-column stores tailored for specific query access patterns.
End-of-Chapter Synthesis & Key Takeaway
SQL vs. NoSQL & Data Model Selection is built around one fundamental rule: Establish clear responsibility and explicit trade-offs.. Before adding components, establish explicit quantitative SLAs for latency, throughput, and consistency. Choose the simplest architecture that meets stated constraints.
Architectural & Technical Interview Review
Core FAANG Interview Questions
Q01How do you justify introducing SQL vs. NoSQL & Data Model Selection into a high-scale production architecture?Click to reveal model answer →Hide answer ↑Requirements & Design Brief
Introduce SQL vs. NoSQL & Data Model Selection only when measured scale, data size, or failure boundaries exceed single-node capacity. State the exact bottleneck, evaluate operational overhead, and verify that the trade-offs justify the added moving parts.
Q02What is the primary trade-off and hidden operational cost of SQL vs. NoSQL & Data Model Selection?Click to reveal model answer →Hide answer ↑Architecture Trade-offs
It improves scalability and availability, but introduces network hops, serialization overhead, and eventual consistency or coordination complexity.
Q03How do you handle catastrophic failure or dependency degradation in SQL vs. NoSQL & Data Model Selection?Click to reveal model answer →Hide answer ↑Failure Review & Recovery
Implement connect/read timeouts, exponential backoff with jitter, and fallback defaults so downstream degradations do not cause cascading outages.
Production Pitfalls & Anti-Patterns
Critical Failure Anti-Patterns
Premature Distributed Complexity
Scattering distributed components before identifying concrete write, read, or storage limits creates accidental points of failure and operational debt.
Production Mitigation: Start with the simplest modular design that satisfies requirements, evolving it only as measured constraints dictate.
Unbounded Retries and Cascading Storms
When a dependency degrades, immediate synchronized retries multiply downstream traffic, turning a minor slowdown into a total fleet outage.
Production Mitigation: Enforce strict retry budgets, exponential backoff, and full randomized jitter on all client calls.
Neglecting Observability and Metrics
Deploying architecture without distributed tracing or p99 tail latency alerts leaves engineers blind when partial partitions occur.
Production Mitigation: Export metrics for request rate, error rate, p95/p99 duration, and saturation at every service boundary.