When relationships are the point — social networks, fraud rings, recommendations — a graph database models nodes and edges as first-class citizens. Learn Neo4j and querying with Cypher.
A graph database stores entities as nodes and the relationships between them as edges, both able to hold properties. The key difference from a relational database is that a relationship is a direct pointer, not a value to be matched with a join at query time. This makes traversing connections — friends of friends, paths, rings — fast even many hops deep, where SQL joins would explode.
Relational: relationships are FOREIGN KEYS, resolved by JOINs at query time.
"friends of friends of friends" = 3 self-joins -> combinatorial blowup.
Graph: a relationship is a stored, direct POINTER between nodes.
(Ann)-[:FRIEND]->(Bob)-[:FRIEND]->(Cara)
traversing hops = following pointers -> fast even 5+ hops deep.
Use a graph when the CONNECTIONS are the question:
social networks, fraud rings, recommendations, knowledge graphs,
network/dependency topology, "shortest path between X and Y".You build a graph by creating nodes with labels (e.g. :Person, :Product) and connecting them with typed, directed relationships (e.g. :PURCHASED), each carrying properties. This model maps naturally onto how we describe domains in words — “a person purchased a product” — which is part of why graph queries read so intuitively.
// Neo4j / Cypher: create labeled nodes and typed relationships
CREATE (ann:Person {name: "Ann"})
CREATE (kbd:Product {name: "Keyboard", price: 40})
CREATE (ann)-[:PURCHASED {on: date("2024-06-01")}]->(kbd)
// the pattern reads like the sentence it models:
// (Person)-[:PURCHASED]->(Product)
// labels (:Person), relationship types (:PURCHASED), and properties
// ({name:...}) all carry data.Graph query languages like Cypher work by drawing the pattern you want to find as ASCII-art and letting the engine match it. This is what makes questions like “what do people who bought what Ann bought also buy?” — a recommendation, and a nightmare in SQL — a short, readable query. Pattern matching over stored relationships is the graph database’s superpower.
// "products bought by people who bought what Ann bought" — a recommendation
MATCH (ann:Person {name: "Ann"})-[:PURCHASED]->(p:Product)
<-[:PURCHASED]-(other:Person)-[:PURCHASED]->(rec:Product)
WHERE rec <> p
RETURN rec.name, count(*) AS score
ORDER BY score DESC LIMIT 5;
// you DRAW the pattern; the engine finds every match. The same query in
// SQL is multiple self-joins and far less readable. Traversals stay fast
// because relationships are stored, not computed.Graph databases excel when connections and multi-hop traversal are central, and they answer path and pattern questions that are painful in SQL. They are not general-purpose: they are weaker for high-volume aggregations, bulk analytical scans, or simple tabular data, where a warehouse or relational store wins. Use a graph for the relationship-heavy slice of your system, often alongside other stores.
Use a graph DB when:
✓ relationships + multi-hop traversal are the core question
✓ shortest path, pattern/ring detection, recommendations, knowledge graphs
✓ the schema of connections is rich and changing
Reach for something else when:
✗ heavy aggregations / analytical scans -> warehouse (columnar)
✗ simple tabular records + transactions -> relational
✗ massive write firehose by key -> wide-column
Graphs are a specialist tool for the connected part of your data — usually
one store among several (next: polyglot persistence).