RizTech Academy logo
RizTech Academy
Databases, and the Shapes They Come InLesson 3 of 740 min

The seven families, and the problem each one solves

"NoSQL" is not a kind of database. It is a word meaning "not the relational one", which lumps together six or seven genuinely different things that solve genuinely different problems. Saying "should we use SQL or NoSQL?" is like asking whether to use a vehicle or a not-vehicle.

This lesson is the map. Seven families, a named example of each, the shape of problem each exists for — and, at the end, the honest advice about which one you should actually start with.

You will not remember all of it today. It is here so that when somebody says "we're thinking about Cassandra", you know what question that is an answer to.

1. Relational

PostgreSQL, MySQL, SQLite, SQL Server, Oracle, MariaDB

Data in tables of rows and columns, with a fixed schema, related to each other by keys, and queried with SQL.

SELECT m.name, b.title, l.due_date
FROM loans l
JOIN members m ON m.id = l.member_id
JOIN books   b ON b.id = l.book_id
WHERE l.returned_at IS NULL;

The shape of problem: data with relationships you care about, where correctness matters more than raw write throughput, and where you will ask questions you have not thought of yet.

What it is uniquely good at:

  • Joins. Combining data across tables at query time, which means you do not have to decide the questions in advance.
  • Constraints. The database refuses invalid data, against every client.
  • Transactions across many rows and tables, with real ACID guarantees.
  • Ad-hoc querying. The single most underrated property — somebody can ask a new question five years later without a schema change.

What it is bad at: storing genuinely unstructured or wildly varying documents; scaling writes across many machines (reads scale easily with replicas, writes are hard); and very high-volume time-series or log ingestion.

Roughly 70% of applications should use this and nothing else.

2. Document

MongoDB, CouchDB, Amazon DocumentDB, Firestore

Data as self-contained documents — in practice JSON — grouped into collections. No fixed schema; two documents in the same collection can have different fields.

{
  "_id": "bk_1",
  "title": "Malgudi Days",
  "author": { "name": "R K Narayan", "born": 1906 },
  "tags": ["short stories", "fiction"],
  "copies": [
    { "barcode": "A001", "condition": "good" },
    { "barcode": "A002", "condition": "worn" }
  ]
}

The shape of problem: data that is naturally a whole document, read and written as a unit, where the shape varies between records and you rarely need to combine across collections.

Good at: storing a nested thing in one round trip with no joins; varying shapes without migrations; and writing fast at scale by sharding.

Bad at: anything needing joins across collections (possible, awkward, slow); multi-document transactions (supported now, and you give up performance); and reporting queries nobody anticipated.

The trap: most data that looks document-shaped is relational data with a shape you have not examined yet. A product catalogue looks like documents until you need "all products by this supplier" and discover the supplier is copied into 40,000 documents. Module 10 is about making this decision properly.

3. Key-value

Redis, Memcached, Amazon DynamoDB, etcd

A dictionary. You put a value under a key and get it back by that key. Frequently, though not always, in memory.

SET session:a91f  "{\"user\":42,\"role\":\"admin\"}"  EX 3600
GET session:a91f
INCR rate:ip:203.0.113.9
ZADD leaderboard 4820 "asha"

The shape of problem: you know the key, you want the value, and you want it in under a millisecond.

Good at: caching, sessions, rate limiting, queues, leaderboards, locks, pub/sub, and counters. Redis in particular has real data structures — lists, sets, sorted sets, hashes, streams — which is what separates it from a plain cache and is why module 11 spends a whole lesson on them.

Bad at: any query that is not "by key". You cannot ask "all sessions for admins" without having built that index yourself.

Almost every production web application has one of these alongside its main database. It is the second database nobody teaches you, which is why this course does.

4. Wide-column

Apache Cassandra, ScyllaDB, HBase, Google Bigtable

Rows keyed by a partition key, with columns that can differ per row, distributed across many machines by design. It looks superficially like a table and behaves very differently.

PRIMARY KEY ((sensor_id), reading_time)
   └ partition key   └ clustering key, sorted within the partition

The shape of problem: enormous write volume, spread across many machines, with queries known in advance.

Good at: writing millions of rows a second; linear scaling by adding nodes; surviving a data-centre failure; time-ordered data within a partition.

Bad at: ad-hoc queries — you design the table for the query, and a query you did not design for may be impossible. No joins. Tunable, not guaranteed, consistency.

How you would recognise the need: you are ingesting sensor data, clickstreams or message history at a volume one PostgreSQL machine cannot write, and you already know every question you will ask.

5. Graph

Neo4j, Amazon Neptune, ArangoDB, and Postgres with recursive CTEs for small cases

Nodes and edges, where the relationships are first-class data with their own properties.

MATCH (a:Member)-[:BORROWED]->(:Book)<-[:BORROWED]-(b:Member)
WHERE a.name = 'Asha'
RETURN b.name, count(*) AS shared ORDER BY shared DESC

The shape of problem: questions about connections, especially at variable depth — "who is connected to whom, through how many hops".

Good at: traversals of unknown depth; shortest paths; recommendations ("people who borrowed this also borrowed…"); fraud rings; dependency graphs; access-control hierarchies.

Bad at: everything else. Aggregating millions of rows, simple tabular reporting, and straightforward CRUD are all worse than in a relational database.

How you would recognise the need: your SQL has four self-joins in it and the depth is not fixed. Note that a recursive CTE in PostgreSQL handles a surprising amount of this, and is the right first answer before adopting a second database.

Elasticsearch, OpenSearch, Apache Solr, Meilisearch, Typesense

An inverted index — a map from every word to the documents containing it — with ranking, stemming, fuzzy matching and faceting.

{ "query": { "match": { "title": "malgudi stories" } } }

The shape of problem: full-text search that a human is typing, where results should be ranked by relevance and a typo should still work.

Good at: relevance ranking; typo tolerance; stemming (so "running" finds "run"); synonyms; faceted filtering; search-as-you-type; highlighting.

Bad at: being a source of truth. It is a derived index. It is also eventually consistent, memory-hungry, and operationally demanding.

The rule: the data lives in your primary database and is copied into the search engine. If the search index is lost you rebuild it. If you cannot rebuild it, you have made a mistake.

And: PostgreSQL's own full-text search is good enough for a surprisingly large number of applications. Reach for Elasticsearch when relevance ranking genuinely matters, not because LIKE '%term%' was slow.

7. Time-series

TimescaleDB, InfluxDB, Prometheus, ClickHouse

Optimised for data that arrives stamped with a time, is written far more than read, is rarely updated, and is queried in ranges and aggregates.

SELECT time_bucket('5 minutes', reading_time) AS bucket, avg(temperature)
FROM readings
WHERE reading_time > now() - interval '24 hours'
GROUP BY bucket ORDER BY bucket;

The shape of problem: metrics, sensor readings, prices, events — append-mostly data, queried by time window.

Good at: ingesting at enormous rates; compressing heavily (10–20× is normal, because consecutive readings are similar); time-bucketed aggregation; automatic retention, dropping data older than N days.

Bad at: updates, joins, and anything not organised by time.

Note that TimescaleDB is a PostgreSQL extension — you often get this family without leaving the database you already have.

And one more, because it is new and you will be asked

Vector

pgvector, Pinecone, Weaviate, Qdrant, Milvus

Stores high-dimensional vectors — embeddings produced by a machine-learning model — and finds the nearest ones.

The shape of problem: "find things similar in meaning to this", which no other family can do. Semantic search, recommendations, and retrieval for language models.

Note pgvector first. It is a PostgreSQL extension, and for anything short of many millions of vectors it removes the need for a separate database entirely. Module 12 covers this properly.

The map, on one page

Family Example You want it when The main cost
Relational PostgreSQL Relationships, correctness, unknown future questions Write scaling across machines
Document MongoDB Whole varying documents, read and written as a unit Joins, and reporting
Key-value Redis You know the key and want it in under a millisecond Any query that is not by key
Wide-column Cassandra Vast write volume, queries known in advance No ad-hoc queries, no joins
Graph Neo4j The relationships are the data, at variable depth Everything that is not a traversal
Search Elasticsearch Ranked full-text search a human is typing Not a source of truth
Time-series TimescaleDB Append-mostly data queried by time window Updates and joins
Vector pgvector Similarity in meaning Young, and needs an embedding model

The honest advice

Three things, and they are the reason this lesson exists rather than a list.

Start with PostgreSQL. Not because it is best at everything — it is not — but because it is good enough at most of these, it is the one you can ask unanticipated questions of, and it is the one you can migrate away from once you know what you actually need. Starting with Cassandra because you might one day have Cassandra's problem is how projects acquire operational burden they never needed.

PostgreSQL absorbs several of these families. JSONB gives you document storage with indexes. Recursive CTEs give you graph traversal. Full-text search is built in. TimescaleDB and pgvector are extensions. A very large number of "we need a second database" conversations end with "actually Postgres does that."

Most real applications end up with exactly two: a relational database for the truth, and Redis for the fast path. That is not a compromise, it is the normal answer, and module 13 is about running more than one without them drifting apart.

The failure mode this lesson is written against: choosing a database because of a conference talk, discovering eighteen months later that you cannot answer a question the business now needs, and finding that migrating is a year of work. Choose for the problem you have, and keep the option of answering questions you have not thought of.

Check your work

Why "SQL or NoSQL" is the wrong question. NoSQL is six or seven different things solving different problems.

Relational, in one line. Relationships you care about, correctness, and questions you have not thought of yet.

The relational property people underrate. Ad-hoc querying — a new question five years later with no schema change.

Document, and its trap. Whole varying documents read as a unit — but most document-shaped data is relational data you have not examined.

Key-value, and why it matters here. Sub-millisecond access by key; almost every production web app has one.

Wide-column, and its price. Vast write volume, at the cost of designing the table per query.

Graph, and what to try first. Variable-depth traversals — but try a recursive CTE in PostgreSQL first.

Search, and the rule. It is a derived index, never the source of truth; if you cannot rebuild it you have made a mistake.

Time-series, and the convenient fact. Append-mostly data by time window — and TimescaleDB is a PostgreSQL extension.

Vector, and what to try first. Similarity in meaning — and pgvector is an extension.

The three pieces of honest advice. Start with PostgreSQL; it absorbs several families; most applications end with exactly two.

The failure mode. Choosing from a conference talk and finding out eighteen months later that migrating costs a year.

Practice

  1. Write down, from memory, the seven families and one example of each.
  2. For each, write the one-sentence shape of problem in your own words.
  3. Take an application you use daily and guess which families are behind it. Justify each.
  4. For each family, invent a question it would answer badly. Be specific.
  5. Find out which databases three companies you have heard of actually use — most have engineering blogs about it.
  6. Look up PostgreSQL's JSONB and decide how much of MongoDB's pitch it covers.
  7. Look up PostgreSQL's full-text search and decide when you would still want Elasticsearch.
  8. Find a project you have built and write what it would gain, and lose, from a document database.
  9. Pick a case where a graph database sounds right and write the SQL you would try first.
  10. List everything a library system stores and assign each to a family. Note how much lands in "relational".
  11. Find one blog post arguing for NoSQL and one arguing against. Note which specific problem each author had.
  12. Write down what you would need to see in your own project before adding a second database.

Official documentation

Next: the relational model, in ten minutes.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship