Neo4j Tutorial: Learn Graph Database from Scratch (2026)
I have used relational databases for most of my career, but the first time I modeled a social network in Neo4j, I felt like I had been writing SQL with one hand tied behind my back. Graph databases treat relationships as first-class citizens, and Neo4j is the most mature option in this space.
We will cover everything from basic node and relationship creation to advanced patterns like shortest-path algorithms, recommendation engines, and graph analytics.
Installing and Starting Neo4j
Neo4j runs as a self-hosted server, as a Docker container, or through Neo4j Aura, the fully managed cloud service. For local development, the easiest path is Neo4j Desktop, which bundles the server, browser-based query editor, and administration tools in a single package.
Once the database is running, open the Neo4j Browser at http://localhost:7474. The default credentials are neo4j / neo4j, and you will be prompted to change the password on first login.
// Start Neo4j via Docker
docker run --publish=7474:7474 --publish=7687:7687 --volume=$HOME/neo4j/data:/data neo4j:5-community
// Connect via Cypher shell
docker exec -it cypher-shell -u neo4j -p password
Cypher: Nodes, Relationships, and Properties
Cypher is Neo4j's query language, designed to be visual and declarative. Nodes are written in parentheses, relationships in square brackets with arrows. Properties are key-value maps. The syntax lets you draw graph patterns directly in your query.
A node can have labels like Person or Movie. Relationships always have a direction and a type. Unlike foreign keys in SQL, relationships in Neo4j are stored as pointers, so traversing them is a constant-time operation regardless of graph size.
CREATE (alice:Person {name: 'Alice', age: 30})
CREATE (bob:Person {name: 'Bob', age: 32})
CREATE (alice)-[:KNOWS {since: 2020}]->(bob)
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CREATE (a)-[:LOVES]->(b)
RETURN a, b
Querying Graphs with Pattern Matching
The real power of Cypher is pattern matching. Instead of writing JOINs across multiple tables, you describe the subgraph you are looking for. The MATCH clause finds paths in the graph that match your pattern.
Variable-length path matching is a standout feature. You can ask for friends-of-friends up to N hops with a single pattern: (a)-[:KNOWS*1..3]->(b). This is exponentially harder in relational databases.
MATCH (alice:Person {name: 'Alice'})
MATCH path = (alice)-[:KNOWS*1..2]-(friend)
RETURN friend.name, length(path) AS hops ORDER BY hops
MATCH (user:Person {name: 'Alice'})-[:LIKES]->(m:Movie)
MATCH (m)<-[:ACTED_IN]-(actor)-[:ACTED_IN]->(rec:Movie)
WHERE NOT (user)-[:LIKES]->(rec)
RETURN rec.title, count(*) AS score ORDER BY score DESC
Graph Data Modeling Best Practices
Modeling for a graph database is different from relational modeling. Instead of normalizing into tables, you think in terms of domain entities and their connections. A common pitfall is treating relationships like join tables with artificial IDs.
Use labels to group similar nodes and create indexes on frequently filtered properties. Avoid overly connected super-nodes (nodes with millions of relationships) because they slow down traversals.
CREATE (u:User)-[:RATED {score: 5}]->(m:Movie)
CREATE INDEX person_name FOR (p:Person) ON (p.name)
CREATE CONSTRAINT unique_email FOR (p:Person) REQUIRE p.email IS UNIQUE
Traversal Performance and Indexing
Neo4j uses native graph storage with index-free adjacency, meaning each node stores direct pointers to its relationships. This makes traversals blisteringly fast.
The Cypher planner uses statistics to choose between index scans and full label scans. Use PROFILE to see the execution plan. If you see NodeByLabelScan on a large label, add an index.
PROFILE MATCH (p:Person {name: 'Alice'})-[:KNOWS]->(friends) RETURN friends.name
CREATE INDEX person_name_age FOR (p:Person) ON (p.name, p.age)
Graph Algorithms and Real-World Use Cases
Neo4j ships with a library of graph algorithms that run directly in the database: shortest path, PageRank, community detection, and centrality measures. You call them as Cypher procedures.
A typical recommendation flow: find what a user likes, traverse to similar items, rank by relevance, and filter out already-consumed items. This runs in a single query without exporting data.
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CALL gds.shortestPath.dijkstra({sourceNode: id(a), targetNode: id(b), relationshipTypes: ['KNOWS']})
YIELD totalCost, nodeIds
RETURN totalCost, nodeIds
Frequently Asked Questions
Is Neo4j free to use?
Neo4j Community Edition is free and open-source under GPL. Enterprise adds clustering, security, and online backup features and requires a commercial license.
When should I use Neo4j instead of PostgreSQL?
Use Neo4j when your application is relationship-heavy: social networks, recommendation engines, knowledge graphs, fraud detection, and supply chain management.
Does Neo4j support ACID transactions?
Yes, Neo4j is fully ACID-compliant. Writes are transactional, and Cypher supports BEGIN, COMMIT, and ROLLBACK semantics.
How do I back up a Neo4j database?
Use neo4j-admin dump command for logical backups: neo4j-admin dump --database=neo4j --to=/backups/mydb.dump. Neo4j Aura handles backups automatically.
Originally published on Ayodhyyya. Last updated June 1, 2026.