Module F-14·22 min read

Access-pattern-first modelling and the four broad datastore shapes — the decision framework, before the deep comparison in P-9.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Module F-14 — Choosing a Data Model: SQL vs NoSQL

What this module covers: "SQL or NoSQL?" is the wrong question, and this module replaces it with the right one: what are your access patterns, and which storage shape serves them? It covers access-pattern-first modelling as a method, the four broad datastore shapes and what each genuinely costs, an honest examination of the claim that NoSQL "scales better" (it scales because it removes the features that are hard to distribute), the case for Postgres as a default and where that case ends, the one decision that's hardest to reverse, and the real price of polyglot persistence — including the dual-write problem that makes two stores harder than twice one store.


Ask About Access Patterns, Not About Databases

The question "should we use SQL or NoSQL?" cannot be answered, because the categories aren't comparable — one names a query language, the other names everything that isn't it. The answerable question is:

What are the queries this system will run, how often, and how much data will they touch?

Answer that and the datastore choice mostly follows. Skip it and you'll pick a datastore for reasons that have nothing to do with your workload — familiarity, a conference talk, or a benchmark measuring something you don't do.

The method, in order:

  1. Enumerate the access patterns. Every read and write the system performs, as concrete statements.
  2. Attach volume and latency to each. Which are hot, which are rare, which are user-facing.
  3. Identify which patterns are known and fixed, and which are unknown or ad-hoc.
  4. Then choose.
text

That list already decides most of the design. R1 and R2 are key-based and would suit almost anything. W1 needs a multi-row atomic transaction, which rules out several options or makes them much harder. R4 is unknown at design time — and unknown access patterns are the single strongest argument for a relational database, because SQL lets you ask questions you didn't plan for.

Analogy: choosing a datastore is choosing a kitchen for a menu you're about to write. A sushi counter and a pizza oven are both excellent and neither is general-purpose. If you don't know the menu yet, you want the kitchen with a stove, an oven, and a fridge — less specialised at everything, capable of anything.

Why this matters in production: the expensive failure isn't picking a "slow" database. It's picking one whose data model can't express a query the business asks for later. "Show me all orders over $500 from customers in Karnataka, sorted by name" is thirty seconds of SQL and a genuine engineering project on a store designed for single-key access.


The Four Shapes

Relational (Postgres, MySQL)

Tables, rows, typed columns, foreign keys, joins, ACID transactions, a declarative query language, and a planner that decides execution for you.

Good at: ad-hoc queries, multi-entity transactions, enforced integrity, aggregation, and adapting to access patterns you didn't anticipate.

Costs: horizontal write scaling is genuinely hard (Module P-6), joins across very large tables get expensive, and schema changes on huge tables need care (Module O-4).

Document (MongoDB, DynamoDB in document mode, Postgres JSONB)

Self-contained documents, usually JSON, retrieved by key. Related data is nested rather than joined.

Good at: aggregates that are read and written as a unit — a product with its variants, a form submission, a CMS page. Flexible shape per document. Fetching the whole entity in one read.

Costs: the nesting that makes reads fast makes cross-document queries hard. Data duplicated across documents must be updated in many places, and a single document has an ACID boundary while a multi-document update generally doesn't (support varies and comes with caveats). Flexible schema means the schema moved into your application code, where nothing enforces it — you will find documents from three eras of your product in the same collection.

Key-Value (Redis, DynamoDB, etcd)

Get and put by key. That's the interface, and the constraint is the point.

Good at: the fastest possible lookup, sessions, caches, feature flags, counters, rate limiters, leaderboards. Scales horizontally almost trivially because keys are independent.

Costs: you can only find things by key. No "all items where X" without maintaining your own secondary index — which means every query pattern you want must be designed in advance and kept consistent by your own code.

Wide-Column (Cassandra, ScyllaDB, DynamoDB, HBase)

Rows grouped by a partition key, sorted within a partition by a clustering key. Built for enormous write throughput and linear horizontal scaling.

Good at: massive write volume, time-series and event data, predictable single-partition queries, multi-datacentre replication as a first-class feature.

Costs: the largest of any option here — you design the table for the query, and a query you didn't design for may be impossible. No joins. Aggregations are your problem. Getting the partition key wrong produces hot partitions or unbounded partitions, and changing it means rewriting the data (Modules P-6, P-9). Frequently you store the same data several times, once per access pattern, and keep the copies consistent yourself.

Graph, time-series, search, and vector stores are also real categories with real justifications — Modules P-9, P-20, and P-21 cover them once there's enough context to compare them properly.


"NoSQL Scales Better" — Examined

The claim is true and the reason matters more than the claim: these systems scale better because they removed the features that are hard to distribute.

  • No joins? Then no node needs data from another node to answer a query.
  • No multi-key transactions? Then no distributed coordination protocol, no two-phase commit, no locks held across the network (Modules A-1, A-3).
  • No ad-hoc queries? Then every query hits a known partition and the system can guarantee its performance.
  • Eventual consistency? Then a write doesn't wait for agreement from other replicas (Modules P-10, P-11).

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.