When relationships become the data: my takeaways on graph models
Some products are not mainly collections of independent records. Their value comes from the connections: who knows whom, which place sits inside another place, which product was bought with another product, or which account is linked to a suspicious transaction.
That is where graph models become useful. They are not a replacement for relational or document databases. They are a better mental model when relationships are dense, varied, and unpredictable in depth.
When a graph is the natural shape
Documents fit data that looks like a tree. Relational databases are comfortable with shared entities and ordinary joins. A graph becomes attractive when the relationships themselves are central to the product and a query may need to follow an unknown number of links.
CHOOSE THE MODEL
Tree-shaped data
-> document model
Shared entities and ordinary joins
-> relational model
Dense, variable-depth connections
-> graph model
A graph is made of nodes and edges
A node, also called a vertex, represents a thing such as a person, location, event, organization, product, or comment. An edge represents a relationship between two nodes.
In a property graph, both nodes and edges can have properties. An edge also has a label that describes the relationship, plus a direction from one node to another.
PROPERTY GRAPH
Node
-> ID + properties
Edge
-> from + to + label + properties
For example, a person can have a BORN_IN edge to a location and a LIVES_IN edge to another location. Locations can connect through WITHIN edges, creating a hierarchy that may be shallow in one country and deep in another.
Property graphs are flexible because any node can connect to any other node. New node types and edge labels can be added as a product grows. That makes them useful for evolving domains such as social networks, recommendation systems, fraud detection, organizational structures, and geographic data.
EXAMPLE PATH
Person
-> LIVES_IN -> city
-> WITHIN -> country
-> WITHIN -> continent
Graphs can live in relational tables, but queries can get awkward
A graph can be stored in relational tables: one table for nodes and another for edges. Indexes on both the source and destination of an edge make forward and backward traversal efficient.
The difficulty appears when a query must follow a variable number of relationships. A person may live in a city, region, state, or country, and the number of steps to the location I need is not fixed. SQL can do this with recursive common table expressions, but the query becomes much more verbose.
Cypher is a declarative graph query language designed around this shape. It matches patterns of nodes and edges instead of making the application manually navigate them.
CYPHER TRAVERSAL
Location
-> follow WITHIN
-> zero or more times
-> reach target region
The optimizer can decide whether to begin from people, from an indexed location, or from a relationship in the middle. The application describes the pattern it needs, not the traversal plan.
Graph databases are not a return to the old pointer-based network databases. Modern graphs allow direct lookup by ID or index, do not require fixed record relationships, and commonly support declarative query languages.
Triple stores use one simple statement format
A triple store represents every fact as a subject, predicate, and object. The object can be a simple value or another node. This means the same model represents both properties and relationships.
TRIPLES
Property
-> (lucy, age, 33)
Relationship
-> (lucy, marriedTo, alain)
RDF is a common triple format. It often uses URI namespaces so data from different systems can avoid accidentally giving the same name two conflicting meanings. That is useful even if I have no interest in the broader semantic web vision.
SPARQL is a declarative language for matching triple patterns. It treats properties and relationships uniformly, so the same query style can match a person's name, birthplace, and a variable-length chain of locations.
SPARQL
-> match triple patterns
-> follow relationship paths
Datalog builds complex graph logic from rules
Datalog stores facts in a form similar to triples, then defines rules that derive new facts. A recursive rule can determine whether one location is within another, even through several intermediate places. Later rules can reuse that derived relationship.
This takes a different mindset than one large SQL query. Instead of writing the final query all at once, I can define small reusable rules and compose them into more complex questions.
DATALOG
facts + reusable rules
-> derived relationships
-> complex graph queries
Datalog can feel heavy for a one-off query, but it is valuable when complex relationship logic needs to be reused.
My graph-model checklist
I will consider a graph model when connections are part of the product, when new relationship types are likely, or when queries need to traverse an unknown number of hops.
- Use documents for mostly self-contained tree-shaped data.
- Use relational modeling for shared entities and ordinary joins.
- Use a graph when dense, flexible, variable-depth relationships are central.
A graph can be represented in relational tables, and relational or document data can be reshaped in other ways. But forcing one model to imitate another often creates unnecessary complexity. The better choice is the model that makes the application's common relationships and questions feel natural.
These are my personal learning notes from Designing Data-Intensive Applications by Martin Kleppmann.