RizTech Academy logo
RizTech Academy
The Other FamiliesLesson 2 of 535 min

Graph databases: when the relationships are the data

Some data is mostly about connections. Who follows whom, which account transferred to which, what depends on what, how you are related to a stranger through mutual friends. When the relationships are the point — not an incidental foreign key but the actual thing you query — a graph database earns its place. Neo4j is the best-known; Amazon Neptune and others follow the same idea.

The problem: relationships that go deep

Relational databases handle relationships through joins, and for one or two levels that is fine. The trouble is depth. Consider "friends of friends of friends" on a social network:

-- three levels deep, relationally
SELECT DISTINCT f3.friend_id
FROM friendships f1
JOIN friendships f2 ON f2.user_id = f1.friend_id
JOIN friendships f3 ON f3.user_id = f2.friend_id
WHERE f1.user_id = 42;

Each level is another self-join, and the cost multiplies at each hop — the fan-out from module 5. Six degrees of separation is a six-way join over a table of millions, and it can become minutes or simply infeasible. "Shortest path between two people", "all accounts within four transfers of this one" — these are painful or impossible to express in SQL, and ruinous to run.

The reason is structural: a relational join searches for matching rows by value at query time (even with an index, it is a lookup per row). A graph database instead stores, on each node, direct pointers to its neighbours — so traversing an edge is following a pointer, not searching a table. This is called index-free adjacency, and it is the whole trick: traversal cost depends on how much of the graph you touch, not on how big the graph is. Friends-of-friends costs the same on a graph of a thousand or a billion, as long as the neighbourhood you walk is the same size.

The model: nodes, relationships, properties

A graph is:

  • Nodes — the entities (a person, an account, a product).
  • Relationships — typed, directed edges between nodes (FOLLOWS, TRANSFERRED_TO, DEPENDS_ON). Relationships are first-class: they have a type, a direction, and their own properties.
  • Properties — key-value pairs on both nodes and relationships (a person's name; a transfer's amount and date).

Neo4j's query language is Cypher, and its genius is that it draws the pattern as ASCII art:

// nodes in (parentheses), relationships in [brackets], arrows for direction
CREATE (kavita:Person {name: 'Kavita'})-[:FOLLOWS]->(ravi:Person {name: 'Ravi'})

// friends of friends of friends — the query that hurts SQL
MATCH (me:Person {name: 'Kavita'})-[:FOLLOWS*3]->(fof)
RETURN DISTINCT fof.name

// shortest path between two people
MATCH p = shortestPath(
  (a:Person {name: 'Kavita'})-[:FOLLOWS*]-(b:Person {name: 'Anjali'})
)
RETURN p

(a)-[:FOLLOWS]->(b) literally looks like the relationship it matches, and [:FOLLOWS*3] means "follow this edge three times". The variable-depth traversal (*) and shortestPath are one-liners that have no clean SQL equivalent at all. That expressiveness for connected queries is the headline benefit — the query reads like the question.

Where graphs genuinely win

The pattern is: the relationships are the data, and you traverse them, often to variable depth.

  • Social networks — friends-of-friends, mutual connections, "people you may know", degrees of separation.
  • Recommendation engines — "customers who bought this also bought", "products connected to things you liked" — traversing a web of associations.
  • Fraud detection — rings of accounts connected through shared devices, addresses or transfers; finding the cycle is a graph query and a nightmare in SQL.
  • Knowledge graphs — entities and their relationships, the structure behind many question-answering and search features.
  • Network and dependency mapping — infrastructure topology, package dependency trees, "what breaks if this service goes down".
  • Identity and access — who can reach what through chains of group memberships and permissions.

If your questions routinely contain "connected to", "path between", "within N hops of", or "related through", that is the signal.

Where graphs lose

As specialised as any family here, and the wrong default for most applications:

  • Simple, tabular, aggregate-heavy data. "Total sales by month" is a relational GROUP BY; a graph adds nothing and complicates everything.
  • When relationships are shallow. One or two joins deep, a relational database is faster and simpler. The graph's advantage only shows at depth.
  • Bulk analytics across all nodes. Graphs are optimised for traversing from a starting point, not scanning the whole dataset for aggregates.
  • Operational maturity. A separate specialised system to run, back up, and staff; the ecosystem is smaller than PostgreSQL's.

And PostgreSQL can go surprisingly far before you need a dedicated graph database: a recursive CTE (WITH RECURSIVE) handles hierarchies and moderate-depth traversals, and the pgRouting and Apache AGE extensions add real graph capability. For a modest amount of connected data, staying in PostgreSQL is often right — the same "one system is simpler" argument as everywhere in this course.

How to recognise the need

Choose a graph database when:

  • Relationships are central, queried as much as or more than the entities themselves.
  • Traversals go deep or to variable depth — three or more hops routinely, or "shortest path".
  • The connection patterns matter — rings, paths, mutual links, reachability.
  • The relational version is a pile of self-joins that are slow or unwritable.

And do not, when your data is fundamentally tabular, your relationships are shallow, or a recursive CTE in the database you already run would do. The test: are you querying the connections themselves, to depth? Yes — consider a graph. No — you have a relational schema with foreign keys, and that is fine.

Check your work

When a graph database earns its place. When the relationships are the data and you traverse them, often to variable depth.

Why deep relationships hurt relational databases. Each level is another self-join and the cost multiplies per hop (fan-out).

Index-free adjacency. Each node stores direct pointers to its neighbours, so traversing an edge follows a pointer instead of searching a table.

Its consequence. Traversal cost depends on the neighbourhood you touch, not the size of the whole graph.

The three parts of the model. Nodes, typed and directed relationships (first-class, with their own properties), and properties on both.

What Cypher's syntax mimics. The shape of the pattern — (a)-[:FOLLOWS]->(b) looks like the relationship.

Two queries with no clean SQL equivalent. Variable-depth traversal ([:FOLLOWS*3]) and shortestPath.

Five domains where graphs win. Social networks, recommendations, fraud detection, knowledge graphs, dependency/network mapping.

The signal words. "Connected to", "path between", "within N hops", "related through".

Where graphs lose. Tabular aggregate data, shallow relationships, whole-dataset analytics, and the extra operational cost.

PostgreSQL's own graph reach. Recursive CTEs, and the pgRouting / Apache AGE extensions — often enough for modest connected data.

Practice

  1. Write the SQL for "friends of friends of friends" as three self-joins. Reason about its cost on a million-row friendship table.
  2. Write the same in Cypher with [:FOLLOWS*3]. Compare the readability.
  3. Explain index-free adjacency in your own words, and why it makes graph size irrelevant to a local traversal.
  4. Model a small social graph as nodes and relationships. Add a property to a relationship (e.g. since on FOLLOWS).
  5. Describe a fraud-detection query ("accounts sharing a device within three transfers") and why it is hard in SQL.
  6. Write a WITH RECURSIVE query in PostgreSQL to traverse a hierarchy, and note where it stops being pleasant.
  7. Take an application you know and decide whether any part of it is genuinely graph-shaped. Be honest — most are not.
  8. For one that is not, explain why foreign keys and a couple of joins are the better answer.

Official documentation

Next: search engines, and why LIKE is not search.

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