Module 07 · Databases · Lesson 12 of 13
Graph databases
Nodes, edges and properties as first-class data. Why multi-hop traversals run in constant time per hop, where graph stores win (recommendations, fraud rings, access control), and when a relational join table is enough.
Why it matters
"Friends of friends who like this band and live nearby" is three hops across millions of nodes. In SQL it is a self-join on a self-join with a filter, and the planner's cost grows with the size of every table touched. Graph databases store relationships as physical pointers, so each hop costs the same regardless of how big the graph is. That one property makes a class of queries practical that are otherwise impossible, and knowing exactly which class keeps you from reaching for a graph store when a join table would do.
The idea
A property graph has nodes (entities with labels and properties), edges (directed, typed relationships with their own properties) and queries expressed as pattern matches and traversals. In Cypher, MATCH (me:User)-[:FRIEND]->()-[:FRIEND]->(fof) WHERE fof.city = me.city RETURN fof reads almost like the question.
Index-free adjacency
The reason traversals are fast is that each node stores direct references to its edges and each edge to its endpoints. Following a relationship is a pointer dereference, not an index lookup, so the cost of a hop depends on the node's degree, not on the total number of nodes or edges. A relational join must look up matching keys in an index whose size grows with the table. For queries of depth two and beyond, that difference is orders of magnitude.
Where graphs win
| Use case | Why a graph fits |
|---|---|
| Social and recommendation | Friends of friends, people who bought this also bought, collaborative filtering over multi-hop paths |
| Fraud and risk | Rings of accounts sharing devices, addresses and cards; the pattern is the shape of the subgraph, not any single record |
| Access control and dependencies | Who can see this document through groups and inheritance; which services break if this one fails |
| Knowledge graphs | Entities and typed relationships from many sources, queried by pattern |
| Network and route analysis | Shortest path, reachability, centrality over roads, supply chains or infrastructure |
The common thread is variable-depth traversal or pattern matching where the query is about the shape of connections. If every query is one or two fixed hops, a relational schema with a well-indexed join table performs comparably and keeps the rest of the system simpler.
Where graphs lose
Aggregates over the whole graph ("average order value by month") are analytics questions, and graph stores are poor at them compared with columnar warehouses. Very high write rates of simple records waste the model. Horizontal scaling is hard: a graph does not partition cleanly because edges cross any boundary you draw, so most graph databases scale vertically or replicate whole copies for reads, and distributed graph systems accept cross-partition hops as expensive. Keep the graph focused on the relationships that need traversal and leave bulk attributes in the primary store.
Operating one
Model edges as the verbs of your domain and keep properties on edges where they belong (since, weight). Index node properties used as traversal entry points (the user you start from), because the first lookup is an index hit even if the hops are not. Treat the graph as a derived store fed from the system of record when it serves one feature (recommendations), or as the system of record only when the graph is the product (a knowledge graph). Query languages differ (Cypher, Gremlin, GQL is the emerging standard); the concepts are the same.