Top 60 Neo4j Interview Questions (2026)

The 60 Neo4j questions interviewers actually ask, with direct answers, runnable Cypher, and what the interviewer is listening for. Grouped for freshers, intermediate, and experienced rounds.

60 questions with answers

What Is Neo4j?

Key Takeaways

  • Neo4j is a native graph database that stores data as nodes, relationships, and properties instead of tables.
  • You query it with Cypher, a declarative pattern-matching language where relationships are first-class citizens.
  • It fits connected data like fraud rings, recommendations, and networks, where relational JOINs get slow and messy.
  • This page is a question bank: work your tier first, read one tier up, and say answers out loud because delivery is evaluated too.

Neo4j is a native graph database that models data as nodes (entities), relationships (the connections between them), and properties (key-value data on both). Instead of splitting connected data across tables and reassembling it with JOINs, Neo4j stores relationships directly on disk, so traversing from one node to its neighbors is a constant-time pointer hop no matter how large the dataset grows. You query it with Cypher, a declarative language where you draw the pattern you want using ASCII-art arrows like (a)-[:KNOWS]->(b). In interviews, Neo4j questions probe how well you understand the property graph model, Cypher pattern matching, index and constraint design, and when a graph beats a relational store, not memorized syntax. This page collects the 60 questions that come up most, each with a direct answer and runnable Cypher. If you're still building fundamentals, the official Getting Started guide from Neo4j is the canonical path; increasingly the first database round is a live AI coding interview, so pair this bank with our AI interview preparation guides for the format side.

60Questions with answers on this page
3Difficulty tiers: freshers, intermediate, experienced
20+Runnable Cypher snippets you can practice from
45-60 minTypical length of a Neo4j technical round

Watch: Neo4j Course for Beginners

Video: Neo4j Course for Beginners (freeCodeCamp.org, YouTube)

Test yourself and earn a certificate

10 quick questions. Score 70%+ to download your Neo4j certificate.

Jump to quiz

All Questions on This Page

60 questions
Neo4j Interview Questions for Freshers
  1. 1. What is Neo4j and what problem does it solve?
  2. 2. What is the property graph model?
  3. 3. What is Cypher?
  4. 4. What is the difference between a node and a relationship?
  5. 5. What are labels and how are they used?
  6. 6. What is the difference between CREATE and MERGE?
  7. 7. What does the MATCH clause do?
  8. 8. What does the RETURN clause do?
  9. 9. How does the WHERE clause work in Cypher?
  10. 10. How do you create a relationship between two nodes?
  11. 11. What is the difference between DELETE and DETACH DELETE?
  12. 12. How do you update properties and labels with SET and REMOVE?
  13. 13. Are relationships in Neo4j directed, and can you query without direction?
  14. 14. How does Cypher compare to SQL?
  15. 15. What is a graph in the context of a graph database?
  16. 16. What are common use cases for Neo4j?
  17. 17. How do ORDER BY, SKIP, and LIMIT work in Cypher?
  18. 18. How do you aggregate data in Cypher?
  19. 19. What is Neo4j Browser and what is it used for?
  20. 20. What does the WITH clause do in Cypher?
  21. 21. Where can properties be stored in Neo4j?
  22. 22. What does DISTINCT do in Cypher?
Neo4j Intermediate Interview Questions
  1. 23. What is index-free adjacency and why does it matter?
  2. 24. How do variable-length relationship patterns work?
  3. 25. How do you find the shortest path between two nodes?
  4. 26. What kinds of indexes does Neo4j support and when do you need one?
  5. 27. What constraints does Neo4j support?
  6. 28. What is the difference between EXPLAIN and PROFILE?
  7. 29. How do collect() and UNWIND relate?
  8. 30. What does OPTIONAL MATCH do?
  9. 31. How do you model a domain in Neo4j versus a relational schema?
  10. 32. Why should you use parameters in Cypher queries?
  11. 33. How do you import data with LOAD CSV?
  12. 34. What is APOC and when do you reach for it?
  13. 35. How do transactions work in Neo4j?
  14. 36. Does relationship direction affect query performance, and how should you model it?
  15. 37. How does implicit grouping work with aggregation in Cypher?
  16. 38. How does Neo4j handle null and missing properties?
  17. 39. Which built-in Cypher functions come up most?
  18. 40. How do you model a many-to-many relationship in Neo4j?
  19. 41. How does the CASE expression work in Cypher?
  20. 42. You have a slow Cypher query. How do you tune it?
  21. 43. How do applications connect to Neo4j?
Neo4j Interview Questions for Experienced Engineers
  1. 44. How does Neo4j store data on disk?
  2. 45. How do you scale Neo4j?
  3. 46. What consistency guarantees does Neo4j provide, especially in a cluster?
  4. 47. What causes a cartesian product in Cypher and how do you avoid it?
  5. 48. What is the Eager operator and why can it hurt writes?
  6. 49. What is the supernode (dense node) problem and how do you handle it?
  7. 50. What is the Graph Data Science library and what does it offer?
  8. 51. When and how do you use planner hints in Cypher?
  9. 52. How would you model time-series or versioned data in a graph?
  10. 53. How do you back up and restore a Neo4j database?
  11. 54. How does access control work in Neo4j?
  12. 55. How do you approach migrating a relational database to Neo4j?
  13. 56. How do you configure memory for a Neo4j instance?
  14. 57. When would you NOT use Neo4j?
  15. 58. How does Neo4j handle concurrent writes and locking?
  16. 59. Design question: how would you build a fraud detection system on Neo4j?
  17. 60. How can an index help ORDER BY and range queries, and where does it stop helping?

Neo4j Interview Questions for Freshers

Freshers22 questions

The fundamentals every entry-level round checks. If any answer here surprises you, that's your study list.

Q1. What is Neo4j and what problem does it solve?

Neo4j is a native graph database that stores data as nodes, relationships, and properties instead of tables. It's built for connected data: social networks, recommendations, fraud detection, and anything where the links between records matter as much as the records.

It solves the problem relational databases struggle with: querying many hops of relationships. Where a SQL query needs a JOIN per hop, Neo4j stores relationships directly and follows them like pointers, so traversal stays fast as the graph grows.

Key point: Lead with the one-line definition, then The concrete use case. Interviewers open with this to hear how you frame connected data versus tables.

Watch a deeper explanation

Video: Training Series: Introduction to Neo4j (Neo4j, YouTube)

Q2. What is the property graph model?

The property graph model has three parts. Nodes are the entities (a Person, a Product), relationships connect two nodes and always carry a type and a direction, and properties are key-value pairs stored on both nodes and relationships. Labels group nodes into categories on top of that, and together these pieces describe both the things and the links between them.

Labels group nodes into categories, like :Person or :Movie, and one node can carry several labels. This is what makes Cypher patterns readable: you describe entities, the links between them, and the data on each.

cypher
CREATE (asha:Person {name: 'Asha', age: 31})
CREATE (hyring:Company {name: 'Hyring'})
CREATE (asha)-[:WORKS_AT {since: 2023}]->(hyring)

Key point: The all three parts (nodes, relationships, properties) plus labels. Skipping labels is the usual sign someone has only read about Neo4j, not used it.

Q3. What is Cypher?

Cypher is Neo4j's declarative query language. You describe the pattern you want with ASCII-art arrows, and the engine figures out how to find it. So (a)-[:KNOWS]->(b) reads almost like a diagram of two people connected by a KNOWS relationship, which is what makes reading and writing graph queries feel visual rather than abstract.

It borrows ideas from SQL (clauses like WHERE, ORDER BY, and aggregation) but centers on graph patterns. The core read clause is MATCH, and the core write clauses are CREATE and MERGE.

cypher
MATCH (p:Person)-[:KNOWS]->(friend:Person)
WHERE p.name = 'Asha'
RETURN friend.name

Watch a deeper explanation

Video: Neo4j Cypher Basics: Reading and Writing Data (Neo4j, YouTube)

Q4. What is the difference between a node and a relationship?

A node represents an entity, something that exists on its own: a person, a product, an account. A relationship connects exactly two nodes, always has a type (like :BOUGHT), and always has a direction from a start node to an end node, so it describes how two entities relate rather than existing independently the way a node does.

Both can hold properties. A relationship's properties often describe the connection itself, like a rating on a :REVIEWED relationship or a date on :WORKS_AT.

Key point: The detail the question needs: relationships always have a direction stored, even though you can query them ignoring direction. Say both facts.

Q5. What are labels and how are they used?

A label is a tag that groups nodes into a category, written with a colon like :Person. Labels let you scope queries to one kind of node, and they're what indexes and constraints attach to, so labeling nodes well is the foundation of both fast lookups and data integrity.

A node can have zero, one, or several labels at once. A node might be both :Person and :Employee, and a query can match on either.

cypher
MATCH (e:Person:Employee)
RETURN e.name

// add a label to an existing node
MATCH (p:Person {name: 'Asha'})
SET p:Manager

Q6. What is the difference between CREATE and MERGE?

CREATE always adds new data, so run it twice with the same values and you get two identical nodes. MERGE is get-or-create: it looks for the pattern, uses it if it already exists, and creates it only if it doesn't. That difference is what makes MERGE the safe choice when importing records that might already be in the graph.

Use CREATE when you know the data is new, and MERGE when you want to avoid duplicates, like importing records that may already exist. MERGE pairs with ON CREATE SET and ON MATCH SET to set properties differently in each case.

cypher
MERGE (p:Person {email: 'asha@example.com'})
ON CREATE SET p.created = timestamp()
ON MATCH SET p.lastSeen = timestamp()
RETURN p

Key point: The trap is calling MERGE 'CREATE if not exists' and stopping. Mention that MERGE matches on the WHOLE pattern, so a partial MERGE can create more than you expect.

Watch a deeper explanation

Video: Introduction to Neo4j: a hands-on crash course (Neo4j, YouTube)

Q7. What does the MATCH clause do?

MATCH finds patterns in the graph. You draw nodes and relationships as a pattern, and Cypher returns every subgraph that fits it. It's the read counterpart to CREATE and the starting point of almost every query, because you have to locate data before you can filter, return, update, or delete it.

MATCH followed by WHERE filters results, and RETURN shapes the output. Without a MATCH, there's nothing to filter or return from an existing graph.

cypher
MATCH (m:Movie)<-[:ACTED_IN]-(a:Person)
WHERE m.released > 2000
RETURN m.title, collect(a.name) AS cast

How a Cypher MATCH query runs

1Draw the pattern
MATCH describes nodes and relationships as a pattern to find in the graph.
2Traverse the graph
Cypher walks relationships from anchor nodes, collecting every subgraph that fits.
3Filter with WHERE
WHERE trims the matched rows by property or predicate conditions.
4Shape with RETURN
RETURN projects the columns, and aggregations like collect group the output.

Start MATCH from the most selective node so the traversal touches the fewest paths.

Q8. What does the RETURN clause do?

RETURN specifies what a query sends back: node properties, whole nodes, relationships, paths, or computed values. It's the last clause in a read query and shapes the result set, similar to SELECT in SQL, so choosing what to RETURN is how you turn a matched pattern into exactly the columns your application needs.

You can return expressions, alias columns with AS, and use DISTINCT to drop duplicate rows. Write queries that only fail don't RETURN anything, like a pure CREATE or DELETE.

cypher
MATCH (p:Person)
RETURN DISTINCT p.city AS city, count(*) AS people
ORDER BY people DESC

Q9. How does the WHERE clause work in Cypher?

WHERE filters the rows produced by MATCH, keeping only those that meet a condition. It supports comparisons, boolean logic with AND and OR, string predicates like STARTS WITH and CONTAINS, list membership with IN, and existence checks on whole patterns, so you can filter on structure as well as on property values.

A useful trick: WHERE can also filter on whether a pattern exists, so you can keep only people who have (or don't have) a certain relationship without returning it.

cypher
MATCH (p:Person)
WHERE p.age > 25 AND p.name STARTS WITH 'A'
  AND EXISTS { (p)-[:WORKS_AT]->(:Company) }
RETURN p.name

Q10. How do you create a relationship between two nodes?

First match the two nodes you want to connect, then use CREATE or MERGE with the relationship pattern between them. The relationship needs a type and a direction, and it can carry its own properties like a date or a weight. Matching the nodes before connecting them is what keeps you from accidentally creating duplicates.

A common beginner bug is running CREATE on the full pattern when the nodes already exist, which duplicates the nodes. Match them first, then create only the relationship.

cypher
MATCH (a:Person {name: 'Asha'}), (b:Person {name: 'Ben'})
MERGE (a)-[:KNOWS {since: 2021}]->(b)

Key point: Show that you MATCH existing nodes before connecting them. Creating the whole pattern in one CREATE is the classic duplicate-node mistake.

Q11. What is the difference between DELETE and DETACH DELETE?

DELETE removes a node or relationship, but Neo4j refuses to delete a node that still has relationships, to protect graph integrity and avoid dangling connections. DETACH DELETE removes the node and all its relationships in one step, which is what you want when you're deleting an entity that's still connected to the rest of the graph.

For relationships alone, plain DELETE is fine. For nodes with connections, you either delete the relationships first or use DETACH DELETE.

cypher
// fails if the person has any relationships
MATCH (p:Person {name: 'Asha'}) DELETE p

// removes the node and its relationships
MATCH (p:Person {name: 'Asha'}) DETACH DELETE p

Watch a deeper explanation

Video: Neo4j Course for Beginners (freeCodeCamp.org, YouTube)

Q12. How do you update properties and labels with SET and REMOVE?

SET assigns properties or adds labels: SET p.age = 32 updates a property, SET p:VIP adds a label, and SET p += {city: 'Pune'} merges a map of properties into the node. REMOVE does the opposite, deleting a named property or stripping a label, so together they cover every in-place change to existing nodes.

SET with = on a map replaces all properties, while += merges. Mixing those up is a frequent source of accidentally wiped properties.

cypher
MATCH (p:Person {name: 'Asha'})
SET p.age = 32, p += {city: 'Pune'}
SET p:VIP
REMOVE p.tempFlag

Q13. Are relationships in Neo4j directed, and can you query without direction?

Every relationship is stored with a direction, from a start node to an end node, and there's no such thing as a truly undirected relationship on disk. Direction always exists physically even when your query chooses to ignore it, which is why you model direction to carry meaning like who follows whom.

But you can query ignoring direction by omitting the arrow: (a)-[:KNOWS]-(b) matches the relationship whichever way it points. So you store direction once and read it either way.

cypher
// direction ignored in the match
MATCH (a:Person {name: 'Asha'})-[:KNOWS]-(other)
RETURN other.name

Key point: The precise answer is 'stored directed, queryable undirected.' Saying relationships can be undirected is a small but noticed error.

Q14. How does Cypher compare to SQL?

Both are declarative, and Cypher deliberately reuses SQL ideas so WHERE, ORDER BY, LIMIT, and aggregation all feel familiar. The big difference is how you express connections: SQL matches keys with JOINs at query time, while Cypher draws the relationship directly as a pattern and follows it as a stored link, which is why multi-hop queries stay short and fast.

A multi-hop query that needs several JOINs in SQL becomes a single readable pattern in Cypher, and it stays fast because Neo4j follows stored relationships instead of matching keys at query time.

ConceptSQLCypher
Find recordsSELECT ... FROMMATCH ... RETURN
Connect dataJOIN ON keysPattern with -[:REL]->
FilterWHEREWHERE
InsertINSERT INTOCREATE / MERGE

Q15. What is a graph in the context of a graph database?

A graph is a set of nodes connected by relationships, the mathematical structure behind networks: cities linked by roads, people linked by friendships, web pages linked by hyperlinks. It captures both the things and the connections between them, which is exactly the shape of data where relationships carry as much meaning as the entities.

Neo4j is a property graph specifically, meaning nodes and relationships carry properties and relationships are typed and directed. That's richer than a plain graph of anonymous edges.

Q16. What are common use cases for Neo4j?

Recommendation engines (people who bought this also bought), fraud detection (spotting rings of connected accounts), social networks, network and IT operations mapping, identity and access graphs, and the knowledge graphs behind search and AI systems. Each of these lives or dies on relationship queries, which is why they land on a graph rather than a set of tables.

The common thread is that the value lives in the connections. If your important questions are about how things relate across several hops, a graph fits.

Key point: Pick two use cases and explain why the graph helps, not just name-drop. 'Fraud detection because you traverse rings of shared attributes' beats a list.

Q17. How do ORDER BY, SKIP, and LIMIT work in Cypher?

ORDER BY sorts the result rows by one or more expressions, ascending by default or DESC for descending. LIMIT caps how many rows come back, and SKIP discards rows from the start, so combining SKIP and LIMIT is how you page through a large result set one screen at a time.

The order is ORDER BY, then SKIP, then LIMIT. Getting the sequence right matters when you page through results.

cypher
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age DESC
SKIP 10 LIMIT 5

Q18. How do you aggregate data in Cypher?

Aggregation functions like count(), sum(), avg(), min(), max(), and collect() group rows automatically. Any non-aggregated expression in the same RETURN or WITH becomes a grouping key, so you get grouped results without ever writing an explicit GROUP BY the way you would in SQL.

collect() is the graph-specific favorite: it gathers values into a list, which is how you fold a node's neighbors into one row.

cypher
MATCH (a:Person)-[:ACTED_IN]->(m:Movie)
RETURN a.name, count(m) AS films, collect(m.title) AS titles
ORDER BY films DESC

Q19. What is Neo4j Browser and what is it used for?

Neo4j Browser is the built-in web tool for running Cypher and visualizing results as a graph. You type queries, see nodes and relationships drawn out, and inspect properties, which makes it the default place to explore a database and test queries.

It's separate from Neo4j Desktop (which manages database instances) and Bloom (a business-user visualization tool). In interviews people usually mean Browser when they say they explored the graph.

Q20. What does the WITH clause do in Cypher?

WITH passes results from one part of a query to the next, like a pipe between stages. It lets you aggregate, filter, or reshape data mid-query and then keep going with the reduced result. Anything you don't carry through WITH is dropped from scope, which is both its rule and the source of most WITH confusion.

The common use is filtering on an aggregate: you can't put count() in WHERE directly, so you aggregate with WITH, then filter the result.

cypher
MATCH (p:Person)-[:KNOWS]->(friend)
WITH p, count(friend) AS friends
WHERE friends > 5
RETURN p.name, friends

Key point: The 'filter on an aggregate' example is what interviewers hope you reach for. It shows you understand WHY WITH exists, not just that it passes variables along.

Q21. Where can properties be stored in Neo4j?

On both nodes and relationships. A property is a key-value pair, and values can be strings, numbers, booleans, temporal types, spatial points, or arrays of those. Neo4j doesn't store nested maps as property values, so anything structured beyond an array usually becomes its own related node rather than a field.

Storing data on relationships is a real modeling tool: a rating on :REVIEWED, a weight on :ROUTE, or a since date on :WORKS_AT keeps information about the connection where it belongs.

Q22. What does DISTINCT do in Cypher?

DISTINCT removes duplicate rows from a result. Because a graph pattern can reach the same node through several different paths, a plain RETURN often repeats the same value many times, and DISTINCT collapses those down to one row each so the output reflects unique matches rather than the number of paths that led to them.

It applies to whole rows in RETURN, and it also works inside aggregations like count(DISTINCT x), which counts unique values rather than every occurrence.

cypher
MATCH (p:Person)-[:VISITED]->(c:City)
RETURN DISTINCT c.name AS city

// unique cities per person
MATCH (p:Person)-[:VISITED]->(c:City)
RETURN p.name, count(DISTINCT c) AS cities

Key point: Mention count(DISTINCT x), not just row-level DISTINCT. Interviewers use this to check whether you understand why patterns produce duplicate rows.

Back to question list

Neo4j Intermediate Interview Questions

Intermediate21 questions

For candidates with working experience: Cypher depth, data modeling, indexing, and the questions that separate users from understanders.

Q23. What is index-free adjacency and why does it matter?

Index-free adjacency means each node stores direct physical pointers to its relationships and neighboring nodes. To hop from a node to its neighbors, Neo4j just follows those pointers rather than looking anything up in a global index, so a traversal is closer to pointer chasing in memory than to a database search.

This is why traversal cost depends on how many relationships you walk, not on how large the whole graph is. A friend-of-friend query on a graph of ten million people costs the same as on ten thousand, which relational JOINs can't match.

Key point: This is the single most important internals concept. If you can explain WHY deep traversals stay fast, you've answered the 'why not just use SQL' question before it's asked.

Q24. How do variable-length relationship patterns work?

A relationship pattern with *min..max walks a variable number of hops instead of a fixed one. [:KNOWS*1..3] matches paths of one to three KNOWS relationships, [:KNOWS*] matches any depth, and [:KNOWS*2] matches exactly two hops, so one pattern can express reachability across a range of distances.

These power reachability and friend-of-friend queries. Leave the bounds off and a big graph can explode into huge path counts, so set an upper bound and consider shortestPath for the shortest connection.

cypher
MATCH path = (a:Person {name: 'Asha'})-[:KNOWS*1..3]->(b:Person)
WHERE b.name = 'Ben'
RETURN path
LIMIT 5

Key point: Unbounded * on a dense graph is a real performance trap. the upper bound and shortestPath matters.

Q25. How do you find the shortest path between two nodes?

Use the shortestPath() function around a variable-length pattern, and it returns one shortest path between the two matched nodes. allShortestPaths() returns every path tied for shortest instead of just one, which matters when several routes share the same minimum length and you need to see all of them.

shortestPath is optimized and stops early, so it's far cheaper than matching all variable-length paths and sorting by length. Reach for it whenever the question is 'how are these two connected.'

cypher
MATCH (a:Person {name: 'Asha'}), (b:Person {name: 'Ben'})
MATCH p = shortestPath((a)-[:KNOWS*]-(b))
RETURN p, length(p) AS hops

Q26. What kinds of indexes does Neo4j support and when do you need one?

Neo4j 5 has range indexes (the general-purpose default for equality and range lookups), text indexes (for STRING predicates like CONTAINS and ENDS WITH), point indexes (spatial), full-text indexes (analyzed search), and lookup indexes on labels and relationship types. You pick the index type by the kind of predicate the query runs, and range is the one you reach for most.

You need an index on any property you use to find starting nodes, like an id or email. Without one, the query scans every node with the label. Indexes speed up finding entry points, not the traversal itself, which is already fast.

cypher
CREATE INDEX person_email IF NOT EXISTS
FOR (p:Person) ON (p.email)

// verify it is used
EXPLAIN MATCH (p:Person {email: 'asha@example.com'}) RETURN p

Key point: The key distinction: indexes help you FIND anchor nodes, traversal is fast on its own. Candidates who think indexes speed up relationship-following don't get the model.

Q27. What constraints does Neo4j support?

Node property uniqueness (no two :Person nodes share the same email), node and relationship property existence (the property must be present, an Enterprise feature), and node key constraints (a combination of properties is unique and present, also Enterprise). These are the tools that enforce data integrity in a schema-flexible store where nothing else forces a shape.

A uniqueness constraint also creates a backing index, so it enforces integrity and speeds lookups at once. It's the standard way to guarantee, for example, one node per user id.

cypher
CREATE CONSTRAINT person_email_unique IF NOT EXISTS
FOR (p:Person) REQUIRE p.email IS UNIQUE

Q28. What is the difference between EXPLAIN and PROFILE?

EXPLAIN shows the planner's chosen execution plan with estimated rows, without ever running the query. PROFILE actually runs it and reports the real rows and db hits per operator, which is how you find the step that's actually expensive rather than the one you assumed was. So EXPLAIN is for a quick plan check and PROFILE is for measuring.

Use EXPLAIN to sanity-check that a query hits an index before running it against production, and PROFILE to measure and tune. The metric to watch is db hits: fewer is better.

EXPLAINPROFILE
Runs the queryNoYes
Row countsEstimatedActual
Reports db hitsNoYes
Use forPlan check before runningMeasuring real cost

Key point: Say PROFILE runs the query and EXPLAIN doesn't. People who confuse the two haven't tuned a real query.

Q29. How do collect() and UNWIND relate?

collect() folds many rows into a single list, and UNWIND does the reverse by expanding a list into one row per element. Together they let you group data into lists and then flatten it back out, and they're the pair you use constantly, from reshaping results to importing a batch of records passed in as one list parameter.

UNWIND is also the standard way to process a parameter list, like importing many records from a single query, by unwinding the list and creating a node per element.

cypher
UNWIND [{name: 'Asha'}, {name: 'Ben'}] AS row
MERGE (:Person {name: row.name})

// collect is the inverse
MATCH (p:Person)-[:KNOWS]->(f)
RETURN p.name, collect(f.name) AS friends

Q30. What does OPTIONAL MATCH do?

OPTIONAL MATCH is the graph version of a left outer join. It tries to match a pattern, and when nothing matches, it returns nulls for that part instead of dropping the row entirely. That's the difference from a plain MATCH, which would silently discard any row where the pattern failed to match anything.

Use it when you want every node from the first match even if the optional part is missing, like listing all people with their manager where some people have no manager.

cypher
MATCH (p:Person)
OPTIONAL MATCH (p)-[:REPORTS_TO]->(mgr:Person)
RETURN p.name, mgr.name AS manager

Key point: The 'left outer join' framing lands instantly with anyone from a SQL background and shows you understand the null behavior.

Q31. How do you model a domain in Neo4j versus a relational schema?

Turn nouns into nodes and verbs into relationships. A relational join table that only holds two foreign keys usually becomes a direct relationship in the graph, which removes a whole table and the JOINs through it. So instead of normalizing into many tables, you model the domain the way you'd draw it on a whiteboard.

Ask what questions you'll ask most. Model so the frequent traversals are short and direct. Attributes you filter or return live as properties; things you traverse to live as related nodes.

  • Entities become nodes with labels.
  • Foreign-key relationships and pure join tables become typed relationships.
  • Data about a connection (a rating, a date) becomes a relationship property.
  • Values you filter or display stay as node properties.

Q32. Why should you use parameters in Cypher queries?

Parameters replace literal values with named placeholders like $email. They let Neo4j reuse a single compiled query plan across many calls instead of replanning for every new value, which is a real performance win under load because query planning isn't free and repeats add up fast on a busy service.

They also prevent Cypher injection, the graph equivalent of SQL injection, by keeping user input out of the query text. Application code should always parameterize, never build query strings.

cypher
// parameter passed from the driver as {email: 'asha@example.com'}
MATCH (p:Person {email: $email})
RETURN p

Key point: Mention both reasons: plan-cache reuse AND injection safety. Naming only one is a partial answer.

Q33. How do you import data with LOAD CSV?

LOAD CSV reads a CSV file row by row and lets you build the graph in Cypher. WITH HEADERS gives you named columns to reference, and the usual shape is to MERGE nodes on a stable key and then MERGE the relationships between them, so re-running the import updates rather than duplicating data.

For large files, wrap it in CALL { ... } IN TRANSACTIONS (or the older USING PERIODIC COMMIT) so it commits in batches instead of one giant transaction that exhausts memory. Create constraints first so the MERGE lookups are indexed.

cypher
LOAD CSV WITH HEADERS FROM 'file:///people.csv' AS row
CALL {
  WITH row
  MERGE (p:Person {id: row.id})
  SET p.name = row.name
} IN TRANSACTIONS OF 1000 ROWS

Q34. What is APOC and when do you reach for it?

APOC (Awesome Procedures On Cypher) is Neo4j's standard extension library of procedures and functions. It covers work that plain Cypher can't express directly: dynamic labels and relationship types decided at runtime, JSON and data import helpers, graph refactoring, and batching large operations with apoc.periodic.iterate. Think of it as the utility belt most real projects end up depending on.

Reach for it when you need dynamic behavior (a relationship type decided at runtime) or utility operations that would be painful in plain Cypher. It's installed separately, so confirm it's available before relying on it.

cypher
// create a relationship whose type is a variable
MATCH (a:Person {name: 'Asha'}), (b:Company {name: 'Hyring'})
CALL apoc.create.relationship(a, 'WORKS_AT', {since: 2023}, b) YIELD rel
RETURN rel

Q35. How do transactions work in Neo4j?

Neo4j is ACID. Every Cypher statement runs inside a transaction that either commits fully or rolls back on error, so the graph never ends up half-updated. Drivers let you group several statements into one explicit transaction when you need them to succeed or fail together, which is how you keep related writes consistent.

For big writes, you split work into batches so a single transaction doesn't hold too much in memory. CALL { ... } IN TRANSACTIONS runs sub-batches, each committing on its own.

Q36. Does relationship direction affect query performance, and how should you model it?

Traversing a relationship costs the same in either direction, because each node stores its relationships both ways. So you model direction for meaning (a FOLLOWS b is not the same as b FOLLOWS a), never for speed, and you store the relationship once rather than adding a mirror copy to make traversal faster.

Pick the direction that reads naturally for your domain, store it once, and query with or without the arrow as each question needs. Don't create two relationships to represent one undirected link.

Key point: The 'model for meaning, not speed' point plus 'don't double up relationships' is the mature answer. It shows you know traversal is symmetric in cost.

Q37. How does implicit grouping work with aggregation in Cypher?

Cypher has no GROUP BY. When a RETURN or WITH mixes aggregation functions with plain expressions, the plain expressions automatically become the grouping keys and the aggregation runs once per group. It's concise, but it also means adding an extra non-aggregated column silently changes how your results are grouped.

So RETURN p.city, count(*) groups by city. This is elegant but a common surprise: adding an extra non-aggregated column silently changes the grouping.

cypher
MATCH (p:Person)-[:LIVES_IN]->(c:City)
RETURN c.name AS city, count(p) AS residents
ORDER BY residents DESC

Q38. How does Neo4j handle null and missing properties?

A property that was never set is simply absent, and reading it returns null. There's no schema forcing every node to carry every property, so two :Person nodes can hold completely different property sets. That flexibility is a feature of the model, but it means your queries have to handle missing properties rather than assume them.

null propagates through expressions and comparisons: null = null is null, not true. Use IS NULL and IS NOT NULL to test, and coalesce() to supply a default. OPTIONAL MATCH is the main source of intentional nulls.

cypher
MATCH (p:Person)
RETURN p.name, coalesce(p.nickname, p.name) AS display
ORDER BY display

Q39. Which built-in Cypher functions come up most?

Scalar functions like coalesce() and size(); list functions like range() and reduce(); string functions like toLower() and split(); path functions like length() and nodes(); and predicate functions all() and any() that test a condition across a list. You don't need them memorized, but knowing which category solves a problem speeds up query writing a lot.

For counting, count() is aggregation; for the number of elements in a list, use size(). Confusing those two is a frequent stumble.

Q40. How do you model a many-to-many relationship in Neo4j?

Directly, with a relationship. Where a relational schema needs a junction table (a student_course table holding two foreign keys), Neo4j uses one typed relationship: (student)-[:ENROLLED_IN]->(course), with no extra table and no JOIN through it. That single modeling move is one of the clearest wins a graph gives you over a relational store.

If the connection itself has attributes, like a grade or an enrollment date, they become properties on that relationship. If it has its own identity and further connections, you promote it to a node instead.

cypher
MATCH (s:Student {id: $sid}), (c:Course {code: $code})
MERGE (s)-[e:ENROLLED_IN]->(c)
SET e.enrolledOn = date(), e.grade = null

Key point: The 'junction table becomes one relationship' insight is exactly what a modeling question is screening for. Add the 'promote to a node when it has its own identity' nuance for production signal.

Q41. How does the CASE expression work in Cypher?

CASE returns a value based on conditions, like a conditional expression. The simple form compares one value against options; the generic form (CASE WHEN condition THEN result) evaluates arbitrary boolean tests. It's how you branch inside a RETURN or SET.

cypher
MATCH (p:Person)
RETURN p.name,
  CASE
    WHEN p.age < 18 THEN 'minor'
    WHEN p.age < 65 THEN 'adult'
    ELSE 'senior'
  END AS bracket

Q42. You have a slow Cypher query. How do you tune it?

Run PROFILE and read the operators bottom to top, looking for the ones with the most db hits and rows. The usual culprits are a full label scan where an index should anchor the query, an unbounded variable-length path, or a cartesian product from two disconnected patterns.

Tuning a slow Cypher query

1PROFILE the query
read operators bottom to top, find the high db-hit step
2Anchor with an index
add an index/constraint so the start node is a seek, not a scan
3Bound the traversal
cap variable-length paths, use shortestPath where it fits
4Fix the shape
remove cartesian products, filter early with WHERE, re-PROFILE

The goal is fewer db hits at each step. Re-PROFILE after every change so you know which one helped.

Key point: the method (PROFILE, find the hot operator, fix, re-measure) more than any single trick is the technical point.

Q43. How do applications connect to Neo4j?

Applications use official drivers (Python, Java, JavaScript, Go, .NET, and more) that speak Bolt, a binary protocol built for Neo4j. You create one driver, open sessions from it, run parameterized Cypher inside transactions, and read back records. The driver handles connection pooling, so the pattern is one long-lived driver per application, not one per request.

The driver manages a connection pool, so you create one driver per application and reuse it. HTTP access exists too, but Bolt is the default for performance.

python
from neo4j import GraphDatabase

driver = GraphDatabase.driver('bolt://localhost:7687', auth=('neo4j', 'password'))
with driver.session() as session:
    result = session.run(
        'MATCH (p:Person {email: $email}) RETURN p.name AS name',
        email='asha@example.com')
    print([r['name'] for r in result])
Back to question list

Neo4j Interview Questions for Experienced Engineers

Experienced17 questions

advanced rounds probe internals, scaling, design judgment, and production scars. Expect every answer here to draw a follow-up.

Q44. How does Neo4j store data on disk?

Neo4j uses fixed-size record stores: a node store, a relationship store, a property store, and label and token stores. Fixed-size records mean a node's position is a simple offset, so the engine jumps straight to it. Each relationship record links back to both its nodes and to the previous and next relationships in each node's chain.

That doubly linked relationship chain is what makes index-free adjacency work physically: following a node's relationships is pointer arithmetic through the store, not a lookup. Understanding this is what separates a Neo4j user from someone who knows the engine.

Key point: the storage layout back connects to index-free adjacency. The whole point of fixed-size records and relationship chains is fast pointer traversal.

Q45. How do you scale Neo4j?

Vertically first, since a graph traversal benefits from RAM: size the page cache to hold the working set, and the hot graph is served from memory. Horizontally, Neo4j Enterprise uses a causal cluster with one primary (writes) and read replicas (reads), giving read scale-out and high availability.

For write scale-out and datasets past one machine, Neo4j Fabric shards the graph across databases and queries them together. Sharding a connected graph is genuinely hard, so the honest answer is that most workloads scale up and read-replicate long before they shard.

  • Scale up: large page cache holds the working set in memory.
  • Read scale-out: causal cluster with read replicas.
  • High availability: multiple primaries with Raft consensus.
  • Beyond one machine: Fabric shards across databases.

Key point: The mature note is that sharding a connected graph is hard, so most teams scale up and read-replicate first. Saying 'just shard it' signals inexperience.

Q46. What consistency guarantees does Neo4j provide, especially in a cluster?

A single instance is fully ACID: transactions are serializable and durable. In a causal cluster, writes go to a primary and replicate to others via the Raft protocol, so the cluster is strongly consistent for writes but reads on replicas can lag slightly.

Neo4j solves the read-your-own-writes problem with bookmarks: after a write, the driver gets a bookmark, and passing it to the next read guarantees that read sees at least that write. That's the causal in causal cluster.

Key point: Bookmarks and causal consistency are the senior-level detail. Anyone can say ACID; explaining read-your-writes across replicas shows real cluster experience.

Q47. What causes a cartesian product in Cypher and how do you avoid it?

A cartesian product happens when a single MATCH contains two patterns with no shared variable connecting them. Neo4j pairs every match of the first with every match of the second, so the row count multiplies and the query crawls. The planner even warns about it.

Fix it by connecting the patterns through a relationship, or by splitting them with WITH so each is evaluated and reduced before the next. If you truly need the cross product, make that intent explicit.

cypher
// accidental cartesian product: a and b are unrelated
MATCH (a:Person), (b:Company) RETURN a, b

// fixed: connect them, or use WITH to sequence
MATCH (a:Person)-[:WORKS_AT]->(b:Company) RETURN a, b

Q48. What is the Eager operator and why can it hurt writes?

The planner inserts an Eager operator when a query reads and writes the same data in a way where lazy streaming could corrupt results. Eager forces the whole upstream result to materialize before the write runs, which protects correctness but can blow up memory on a large write.

It commonly appears in LOAD CSV imports that both MATCH and CREATE overlapping patterns. You spot it in PROFILE, then restructure the query, often splitting reads and writes into separate passes, to remove it.

Key point: Knowing Eager exists, why the planner adds it, and how to spot it in PROFILE is a strong production signal. Most candidates have never heard of it.

Q49. What is the supernode (dense node) problem and how do you handle it?

A supernode is a node with an enormous number of relationships, like a celebrity followed by millions or a popular tag on every article. Traversing through it forces the engine to scan a huge relationship list, which slows queries that touch it.

Handling it: rely on Neo4j's dense-node storage that groups relationships by type and direction so it can skip to the relevant group, filter by relationship type and direction early, add properties that let you prune before expanding, or restructure the model to introduce intermediate nodes that break up the fan-out.

Key point: the supernode problem is useful because is a senior tell. Pair it with a concrete mitigation (type/direction filtering or an intermediate node), not just the definition.

Q50. What is the Graph Data Science library and what does it offer?

The Graph Data Science (GDS) library adds graph algorithms that run over an in-memory projection of the graph: centrality (PageRank, betweenness), community detection (Louvain, label propagation), pathfinding (Dijkstra, A*), similarity, and node embeddings. It's a separate analytical layer from the transactional Cypher you write day to day, aimed at questions about structure and influence.

The workflow is project a subgraph into memory, run an algorithm, then write results back or stream them. It's how teams do recommendations, fraud ring detection, and influence analysis at scale, distinct from the transactional Cypher you use day to day.

cypher
CALL gds.graph.project('social', 'Person', 'KNOWS')
CALL gds.pageRank.stream('social')
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS person, score
ORDER BY score DESC LIMIT 10

Q51. When and how do you use planner hints in Cypher?

Hints like USING INDEX, USING SCAN, and USING JOIN tell the planner how to execute a query when its statistics lead it to a bad plan. USING INDEX forces a specific index, which helps when the planner picks a label scan over an available index.

The senior caveat: hints are a last resort. Usually the real fix is updating statistics, restructuring the query, or adding the right index. A hardcoded hint can become wrong as data grows, so document why it's there.

cypher
MATCH (p:Person)
USING INDEX p:Person(email)
WHERE p.email = $email
RETURN p

Q52. How would you model time-series or versioned data in a graph?

Two patterns. For time-series, link events in a chain or them connects to shared time-tree nodes (year, month, day) so range queries traverse the tree instead of scanning every event. For versioning, keep the current entity as one node and attach historical states as related :State or :Version nodes with valid-from and valid-to properties.

The choice depends on your queries. If you ask 'what did this look like on a date', a versioning model with dated relationships answers it by traversal; if you ask 'all events in March', a time tree does.

Q53. How do you back up and restore a Neo4j database?

Neo4j Enterprise supports online backups with neo4j-admin database backup, which captures a consistent snapshot without stopping the database and can take incremental backups afterward. Community edition uses offline dumps with neo4j-admin database dump while the database is stopped, so the tradeoff there is a maintenance window versus the always-on backups Enterprise gives you.

Restore replays a backup or loads a dump into a fresh database. A real answer includes testing restores regularly, because a backup you've never restored is a hope, not a plan.

Q54. How does access control work in Neo4j?

Neo4j Enterprise has role-based access control down to fine granularity: you grant roles permissions on databases, and can restrict access to specific labels, relationship types, and even properties, so a role sees only part of the graph. Community edition has basic user authentication without the fine-grained roles.

Beyond RBAC, you parameterize all Cypher to block injection, run over encrypted Bolt connections, and integrate with LDAP or SSO for user management. Property-level security is the feature people forget Neo4j has.

Q55. How do you approach migrating a relational database to Neo4j?

Model first, don't mirror. Map tables to node labels, foreign keys and pure join tables to relationships, and columns to properties, but redesign around the traversals you actually run rather than copying the schema one-to-one. Then export tables to CSV and import with LOAD CSV or the neo4j-admin bulk importer, creating constraints before the import so MERGE is indexed.

The honest scope note: you usually migrate the connected part of the domain, the part that hurts in SQL, and leave flat transactional tables where they are. A polyglot setup is common, not a failure.

Key point: The insight the question needs is 'model for your queries, don't copy the schema.' A one-to-one table-to-label port that keeps join tables as nodes misses the point of moving.

Q56. How do you configure memory for a Neo4j instance?

Three pools matter: the heap (for query execution and transaction state), the page cache (which holds graph and index data from disk), and off-heap transaction memory. The page cache should be large enough to hold the working set of the graph, because a graph served from the page cache is fast and one hitting disk on every hop is not.

The rule of thumb is size the page cache to the store files you traverse hot, give the heap enough for concurrent queries without long garbage-collection pauses, and leave RAM for the OS. neo4j-admin can estimate the page cache from store size.

Q57. When would you NOT use Neo4j?

When the data isn't connected. Flat, tabular, aggregation-heavy workloads (analytics over independent rows, ledgers, reporting) are what relational and columnar stores are built for, and forcing them into a graph adds complexity for no traversal benefit. If your important queries never walk relationships, a graph is the wrong tool no matter how interesting it looks.

Also skip it for pure key-value caching (Redis fits), for large binary or document blobs, and for workloads that are almost entirely bulk aggregate scans rather than relationship walks. Being able to say when a graph is the wrong tool is a stronger signal than defending it everywhere.

WorkloadBetter fitWhy
Deeply connected traversalsNeo4jRelationships are free to follow
Flat aggregate reportingRelational / columnarOptimized for scans and GROUP BY
Simple cache lookupsRedisLow-latency key-value
Large documents / blobsDocument / object storeBuilt for big nested payloads

Key point: Answering 'when NOT to use it' honestly is the strong move. Interviewers distrust anyone who claims a graph fits every problem.

Q58. How does Neo4j handle concurrent writes and locking?

Neo4j takes write locks on the nodes and relationships a transaction modifies, so concurrent transactions touching the same data serialize rather than corrupt each other. Reads see the version they started with and aren't blocked by writers, which keeps read-heavy workloads fast even while writes are happening on the same graph.

Two things bite in production: deadlocks when transactions grab locks in different orders (Neo4j detects and aborts one, so retry with backoff), and lock contention on a hot node that every write touches. The fix for contention is often a model change to spread writes across more nodes.

Key point: deadlock detection with retry, and hot-node lock contention, matters.

Q59. Design question: how would you build a fraud detection system on Neo4j?

Clarify the fraud pattern first, because that drives the model. Then represent accounts, devices, cards, and addresses as nodes, and shared usage as relationships, so fraud rings show up as tightly connected clusters sharing devices or addresses. Real-time checks run Cypher traversals from a new transaction to see how many hops it connects to known-bad entities; batch analysis runs GDS community detection to surface rings no single query would catch.

Close on the operational edges: index the entry points (account id, device fingerprint) so lookups are seeks, bound the traversals to keep real-time checks fast, and feed scores back as properties or into a downstream model. Structuring the answer as pattern, model, real-time versus batch, operations is what the question is really scoring.

cypher
// accounts sharing a device with a flagged account, within 2 hops
MATCH (bad:Account {flagged: true})-[:USED_DEVICE]->(d:Device)<-[:USED_DEVICE]-(suspect:Account)
WHERE suspect <> bad
RETURN suspect.id, count(DISTINCT d) AS sharedDevices
ORDER BY sharedDevices DESC

Key point: The The technical sequence is (clarify, model, real-time vs batch, operations) more than any single Cypher line.

Q60. How can an index help ORDER BY and range queries, and where does it stop helping?

A range index stores property values in sorted order, so the planner can satisfy an ORDER BY on that property, or a range filter like age > 30, by reading the index in order instead of sorting the whole result. You confirm it in PROFILE: an index-backed plan skips the Sort operator.

It stops helping once the query has already expanded through relationships, because the traversal result isn't in index order anymore. So an index accelerates the anchor step and its ordering, not a sort applied after a multi-hop expansion, where an explicit Sort is unavoidable.

cypher
CREATE INDEX person_age IF NOT EXISTS FOR (p:Person) ON (p.age)

// planner can read the index in order, no Sort operator
PROFILE MATCH (p:Person)
WHERE p.age > 30
RETURN p.name ORDER BY p.age

Key point: The nuance that separates seniors: an index orders the anchor scan, but a sort after relationship expansion still costs a Sort operator. Saying 'an index always removes the sort' is the giveaway that someone hasn't read a real plan.

Back to question list

Neo4j vs Relational Databases and Other Graph Stores

Neo4j wins when data is highly connected and your queries walk many hops of relationships, which is where a relational database piles up expensive JOINs. It trades the mature transactional tooling and rigid schema of a relational store for a flexible model where relationships carry no query-time cost. Against other graph databases, the split is mostly query language and model: Neo4j uses the property graph and Cypher, while RDF stores like Amazon Neptune or GraphDB use triples and SPARQL. Knowing these trade-offs out loud is itself an interview signal: it shows you pick a store on merits, not habit.

SystemData modelQuery languageBest at
Neo4jProperty graph (nodes, relationships)CypherDeep relationship traversal, connected data
PostgreSQL / MySQLTables (rows, columns)SQLStructured transactional data, aggregations
MongoDBDocuments (JSON)MQLNested documents, flexible schema per record
Amazon NeptuneProperty graph and RDFCypher/Gremlin and SPARQLManaged graph on AWS, RDF triples
RedisKey-value and structuresCommandsCaching, low-latency simple lookups

How to Prepare for a Neo4j Interview

Prepare in layers, and practice out loud. Most Neo4j rounds move from concept questions about the graph model to live Cypher on a whiteboard or in Neo4j Browser, then a data-modeling or performance discussion, so rehearse each stage rather than only reading answers.

  • Master your tier's concepts until you can explain nodes, relationships, and Cypher patterns without notes, then read one tier up.
  • Spin up a free Neo4j sandbox or Neo4j Desktop and type every snippet; running Cypher against real data cements it far faster than reading.
  • Practice modeling a domain out loud (a social graph, an org chart) because how you reason about relationships, not just syntax is the technical point.
  • Take the quiz on this page to find weak spots, then revisit those questions before the real round.

The typical Neo4j interview flow

1Recruiter or phone screen
background, motivation, a few graph-model concept checks
2Cypher fundamentals
MATCH, CREATE, MERGE, WHERE, pattern matching, relationships
3Live modeling and queries
design a graph, write traversals, explain your choices
4Performance and design
indexes, constraints, EXPLAIN/PROFILE, when a graph fits

Earlier rounds increasingly run as AI coding interviews. The concepts on this page are what gets probed at every stage.

Test Yourself: Neo4j Quiz

Ready to test your Neo4j knowledge?

10 questions, about 6 minutes. Score 70% or higher to earn a shareable certificate.

10 questions Instant feedback Free certificate on 70%+

Frequently  Asked  Questions

Which Neo4j topics should I prioritize before a technical round?

Prioritize the areas that change real decisions: fundamentals, practical tasks, debugging, trade-offs, and evidence. The highest-value questions are tied to a project example, a validation check, or a failure mode.

Do I need to know Cypher for a Neo4j interview?

Yes. Cypher is the primary way you read and write data in Neo4j, so expect to write MATCH, CREATE, MERGE, and WHERE clauses live. You don't need every function memorized, but you should draw a pattern with arrows, filter it, and return shaped results without hesitating. The snippets on this page cover the clauses that come up most.

Which Neo4j version do these answers assume?

Neo4j 5, the current major line, throughout. The big things to know are that index-free adjacency and Cypher haven't changed conceptually, while syntax details like index creation moved to CREATE INDEX FOR and the deprecated START clause is gone. When in doubt in an interview, say you're answering for Neo4j 5.

How long does it take to prepare for a Neo4j interview?

If you already use Neo4j at work or in study, one to two weeks of an hour a day covers this bank with practice runs. Starting colder, plan three to four weeks and write Cypher daily against a sandbox; reading answers without running queries is how preparation quietly fails.

Do interviewers ask exactly these questions?

The concepts repeat far more reliably than the exact wording. Interviewers rephrase, chain follow-ups, and push toward whatever you claim confidence in. Prepare the underlying ideas, the property graph model, Cypher patterns, MERGE, indexing, and traversal cost, and the phrasing takes care of itself.

Is there a way to test my Neo4j knowledge?

Yes. The quiz on this page scores you as you go and explains every answer, so you find your weak spots fast. Pass the threshold and you can download a shareable certificate with your name and score, free and with no sign-up. It's the quickest way to check yourself before the real round.

From the team that builds coding interviews

Hyring builds the AI Coding Interviewer that runs live technical rounds in 20+ languages for 5,000+ hiring teams. These Neo4j questions and scoring notes reflect what actually gets asked and evaluated inside the interviews we host.

See how the AI Coding Interviewer works

Sources

Adithyan RKWritten by Adithyan RK
Surya N
Fact-checked by Surya N
Published on: 6 May 2026Last updated: 15 Jun 2026
Share: