Key-Value and Graph Models

Two models at opposite ends: one that does almost nothing very fast, and one built entirely around following relationships.

Overview

Key-value: doing less on purpose

The interface is three operations:

get(key)  ->  value
put(key, value)
delete(key)

The value is opaque — a blob the store does not interpret. You cannot query by its contents, sort by it, or join on it. There is no schema and no query language.

That poverty is the point. With no query planner, no join algorithms and no secondary indexes to maintain, a lookup is a hash and a read. Redis, Memcached, DynamoDB in its simplest mode and etcd all live here, and they are fast in a way a general-purpose database cannot match, because they have far less to do.

The cost is that every access path must be designed in advance, encoded in the key. Fetching a user by id means user:1234. Fetching them by email means maintaining a second key, email:ada@example.com -> 1234, and keeping the two in step yourself — there is no unique constraint and no transaction spanning them.

The first variant above shows the shape: a two-column table used as nothing but a key lookup.

Where it fits. Caches, sessions, feature flags, rate limiters, leaderboards, service discovery. Anything with one obvious access path and a strong preference for speed.

Where it does not. Anything needing an ad-hoc question. "How many active sessions are from Leeds" is not answerable without scanning every key, which the model is not built for.

Key-Value and Graph Models

Both models, and the SQL equivalents

query.sql SQLite
Result

Worth knowing

A key-value store supports get, put and delete on an opaque value. That is the entire interface.
The narrowness is the feature: no query planner, no joins, and a lookup that is a hash away.
A graph model makes relationships first-class. Traversing them costs the same whether the graph is small or huge.
In SQL, a graph traversal is a recursive CTE — possible, and verbose enough to show why a dedicated model exists.

Key-Value and Graph Models

The simplest data model and the most relationship-centred one, and when each is worth leaving SQL for.

Graph: relationships as the primary thing

A graph model stores nodes and edges, and both can carry properties. The edges are not derived from matching values, as a foreign key is; they are stored objects, and traversing one is following a pointer.

The difference shows up in queries about *paths*. "Who reports to Ada, directly or indirectly, to any depth" is one traversal in a graph and a recursive CTE in SQL — run the variant and compare it against the ordinary join beside it.

The gap widens with depth. Each level of a relational traversal is another join, and the planner's estimates degrade as they compound; a graph engine follows edges directly, and cost scales with the number of edges actually visited rather than with the size of the tables.

Where it fits. Social networks, org charts, fraud rings, dependency graphs, recommendation paths, network topology, knowledge graphs. The test is whether your interesting questions are about connections rather than about attributes.

Where it does not. Aggregating over millions of rows. A graph engine is usually worse at "total revenue by month" than any relational database.

The honest comparison

Key-valueRelationalGraph
Lookup by idfastestfastfast
Ad-hoc queriesnoyeslimited
Joinsnoyesnative, as traversal
Variable-depth pathsnorecursive CTEnative
Aggregationnoyesweak
Schema enforcementnonestrongusually light

Do you need to leave SQL?

Frequently not, and the variants above are the argument.

A key-value table in Postgres — a primary key and a jsonb column — gets you most of the model with transactions and the option of querying the value later. Redis wins on raw latency; if that is not the binding constraint, the simpler operational story usually is.

Recursive CTEs handle graph traversal, and for a few hundred thousand edges at modest depth they are perfectly good. Dedicated graph engines start winning at deep traversals over large graphs, and at query *expressibility* — Cypher and Gremlin say in one line what a recursive CTE says in fifteen.

The strong argument for a separate store is when the workload is overwhelmingly of one shape. The weak argument is that the model is fashionable.

Where it goes wrong

Using a key-value store as the system of record without a plan for secondary access. The second access path is your problem, forever.

Assuming a graph database is faster at everything. It is faster at traversals and often slower at aggregates.

Recursive CTEs without a depth limit. A cycle in the data is an infinite loop; the variant here carries a guard for exactly that reason.

Modelling everything as a graph. If the questions are about attributes rather than connections, a table is the better graph.

Check yourself

0 of 3

Answer without scrolling back up.

  1. Why is a key-value store fast?

  2. How does a graph edge differ from a SQL foreign key?

  3. What is a graph database usually worse at than a relational one?

Cheat sheet

Key-Value and Graph Models

The value is opaque — a blob the store does not interpret. You cannot query by its contents, sort by it, or join on it. There is no schema and no query language.

DATABASE · vizlearn.in/database/key_value_and_graph_models.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.