When a team first hears "graph database," what usually comes to mind is something from a discrete math course or a picture with nodes and arrows. It seems like a niche thing for social networks and recommendations, and for an ordinary product a relational database is enough. Until you encounter a query like "find everyone connected to this person through two handshakes, and show which companies they mentioned together over the past month." In SQL, such a query turns into a multi-story JOIN that runs for seconds or even minutes and breaks at the slightest schema change. For a deeper dive into this topic, see Serverless Architecture.
That's when the conversation about graphs begins. But there are many myths around the topic: that a graph database is a silver bullet, that it replaces SQL, that it's enough to learn Cypher and everything will work. In practice, it's more complicated and more interesting.
Why relationships are not just another table
A relational database stores relationships through foreign keys and JOINs. Each JOIN is a row-matching operation, and its cost grows with table size. When there are many relationships and they are heterogeneous (friendship, work, purchases, mentions), JOINs become a bottleneck. A graph database stores relationships as first-class entities: each edge has a type, direction, and properties. Traversing a graph is following pointers, not scanning indexes. That's why a "friends of friends" query in a graph database runs in milliseconds where SQL would think for seconds.
But that doesn't mean a graph is always faster. If your queries are aggregates over a single table or simple index lookups, a relational database remains optimal. A graph wins when the main value of the data lies in the relationships, not in the records themselves.
Walkthrough: how to build a "frequently bought together" recommendation
Imagine an online store with 50,000 products and 2 million orders. You need to recommend products that are often bought together with the current one. In SQL, this would be a query with a self-join on the orders table, grouping, and sorting. As data grows, it becomes heavier and heavier.
In the Neo4j graph database, the model looks like this: a Product node, an Order node, a CONTAINS relationship from order to product. To find products bought together, we look for paths of length 2: (p1:Product)<-[:CONTAINS]-(:Order)-[:CONTAINS]->(p2:Product), where p1 is our product. Then we count how many times each pair occurs and sort in descending order.
The Cypher query looks roughly like this:
MATCH (p1:Product {id: $productId})<-[:CONTAINS]-(o:Order)-[:CONTAINS]->(p2:Product)
WHERE p1 <> p2
RETURN p2.name AS recommended, count(o) AS frequency
ORDER BY frequency DESC
LIMIT 10
What's important here: we don't JOIN tables, we traverse the graph. Neo4j uses indexes to find the starting node, then follows relationships stored as pointers. This gives a speed advantage on deep traversals.
But there's a catch: if a product has thousands of orders, a path of length 2 can yield millions of combinations. The query will still be heavy. That's why in real systems constraints are added: only the last N orders are considered, or only orders from the last month. Without such a filter, even a graph database will choke.
Another nuance is deduplication. If the same product was bought in different orders, the counter will grow. But if two products were bought in the same order several times (for example, by mistake), this can distort recommendations. In Cypher, you can use count(DISTINCT o) to count unique orders.
If you do this in a relational database, the query will be more complex and slower. But if you have only 1,000 orders, the difference will be unnoticeable. Graphs shine with volume and depth of relationships.
Where the graph model breaks
Even graph databases have failure modes that aren't visible at the start.
1. "Hot" nodes and supernodes
In a graph there are nodes with a huge number of relationships: a popular product, a famous person, a large city. Traversing such a node requires iterating over all its relationships, which kills performance. In Neo4j this is called the supernode problem. You can spot it in advance from statistics: if a node has tens of thousands of relationships, any query starting from it will be slow. The solution is either to limit traversal by relationship type or properties, or to denormalize and introduce intermediate category nodes.
2. Schema sprawl without control
Graph databases are flexible: you can add new node and relationship types on the fly. This is tempting: every developer adds their own entities. Six months later, nodes User, user, Пользователь, relationships FRIEND, friend_of, дружба appear in the graph. Queries stop finding what's needed, and analytics breaks. The only cure is discipline and a formal schema description (Neo4j has constraints and indexes, but they won't enforce semantics). It's better to establish a naming convention right away and stick to it.
3. False correlations in recommendations
Graph algorithms like PageRank or community detection can produce unexpected results if the data contains noise. For example, if the purchase graph contains a bot that buys everything in sight, it will link unrelated products, and recommendations become meaningless. The algorithm won't understand that this is an anomaly. Preliminary data cleaning and outlier filtering are needed.
Neo4j and Cypher: what to know before starting
Neo4j is the most common graph database. Cypher is its query language, declarative, similar to SQL, but with ASCII art for patterns. It reads almost like natural language: MATCH (a)-[:KNOWS]->(b) RETURN b.name.
Difficulties begin when you need to write efficient queries. Cypher isn't always obviously optimized. For example, traversal order matters. If you start from a node with a million relationships, the query will be slow. You need to use PROFILE or EXPLAIN to see the execution plan.
Another pitfall is transactions and locks. Neo4j supports ACID, but with mass data insertion via LOAD CSV or UNWIND, you can get locks on popular nodes. If you insert 100,000 orders, each referencing the same product, transactions will serialize. The solution is to split insertion into batches and avoid simultaneous updates to the same nodes.
Graph algorithms: not just PageRank
PageRank, shortest path, community detection (Louvain algorithm) are the standard set. They are built into the Neo4j Graph Data Science (GDS) library. But applying them requires understanding what exactly you're looking for.
For example, community detection on a purchase graph can identify groups of products often bought together. But if the data is sparse, the algorithm may find nothing meaningful. Or conversely, it may identify too many small communities. You have to tune parameters (resolution) and validate the result manually.
Another non-obvious point: graph algorithms are sensitive to relationship direction. If in a friendship graph relationships are directed one way (someone followed but not mutually), PageRank will show "authoritative" users but not true friends. You need to either symmetrize relationships or use other algorithms.
Knowledge Graphs: when a graph is not just a database but a knowledge model
A Knowledge Graph is a graph where nodes and relationships have an ontology: classes, hierarchies, inference rules. For example, a company's knowledge graph may contain employees, departments, projects, documents, and relationships between them. It allows answering questions like "who worked on project X together with person Y" taking into account positions and periods.
Such graphs are often built on top of RDF stores or in Neo4j using semantic relationships. They are more complex to design: you need to think through the ontology, determine which relationships are transitive and which are not. Errors in the ontology lead to the graph becoming inconsistent or incomplete.
How this relates to AI/ML
Graphs are increasingly integrated with machine learning. For example, graph embeddings (Node2Vec, GraphSAGE) allow representing nodes as vectors and using them in ML models. This opens the way to recommendations based on graph features.
But there's a trade-off: building embeddings takes time and resources, and quality depends on graph structure. If the graph is sparse, embeddings will be noisy. Moreover, when the graph changes, embeddings need to be recomputed. In some cases, it's easier to use direct graph queries than to build an ML pipeline.
Learning paths: self-study, a course, or practice
Self-studying graph databases is feasible, but it hits the lack of feedback. Neo4j documentation is good, but it won't tell you why your query runs in 10 seconds instead of 100 milliseconds. Forums and Stack Overflow help, but answers don't come immediately, and sometimes not to the right question.
Practice on a real project is the best teacher, but mistakes can be costly: a wrong graph schema leads to rework, and an unoptimized query leads to production downtime.
Courses provide structure and analysis of typical mistakes. For example, the "Graph Databases" course on asibiont.com covers exactly such situations: how to design a schema to avoid supernodes, how to write efficient Cypher queries, and how to integrate graphs with ML. Learning is personalized to the student's level, which helps avoid wasting time on what's already known. But a course doesn't replace practice: without your own experiments, knowledge remains theoretical.
An honest trade-off: self-study is cheaper but slower and risks missing important details. A course provides acceleration and feedback but requires time and money. Practice on a real project is the most effective but also the riskiest path.
Who this suits and who it doesn't
Graph databases are worth learning if you work with highly connected data: social networks, recommender systems, fraud detection, identity management, logistics. If your data is mostly flat tables with rare relationships, you're unlikely to need graphs.
Don't go into graphs if you expect them to replace SQL in all scenarios. It's a tool for specific tasks, not a universal solution. Also don't if you're not ready to delve into algorithms and data structures: graph queries require thinking in terms of paths and patterns.
In conclusion
Graph databases are a powerful tool, but with limitations and pitfalls. They don't replace relational databases but complement them where relationships matter more than records. If you're ready to invest time in learning, the course Graph Databases provides a structured path and analysis of real cases that are hard to find in documentation. You can start with practice on small datasets, gradually moving to more complex scenarios. For a deeper dive into this topic, see BI Analytics and Dashboards.