Neo4j
Master Neo4j: graph database modeling, Cypher queries, and building knowledge graph applications.
What is Neo4j?
Neo4j is a transactional graph database that stores business entities as nodes and their connections as typed relationships. Cypher queries describe the pattern to find, such as an account that transferred money to another account owned by the same device.
Neo4j matters when the useful answer depends on following connections, such as an account that sent money to another account controlled by the same device. A relational database can represent the same facts, but repeated joins become awkward when a path has variable depth, several relationship types, or many possible branches.
The core invariant is a relationship connects two existing nodes, and every committed transaction satisfies the graph's declared constraints. Graph storage makes navigation direct; it does not make an unbounded search cheap.
New to databases? Start with Database Fundamentals for records, indexes, transactions, and replication.
Read the property graph as connected facts
A property graph is a data model made from nodes, relationships, labels, and properties. Each element has one specific job.
Things with identity
Nodes
An Account, Person, or Device node represents an entity that can participate in many facts. A stable domain identifier lets the application find the same entity again.
Typed connections
Relationships
(:Account)-[:SENT_TO]->(:Account) stores a named, directed fact. A relationship can carry properties such as at, amount, or role when they describe that connection.
Roles and entry points
Labels
Labels such as Account and Merchant classify nodes for constraints, indexes, and query planning. A node may have more than one label.
Values on facts
Properties
Properties hold scalar, temporal, spatial, or list values. Keep large blobs in object storage and place only the graph-relevant metadata in Neo4j.
Index-free adjacency needs a precise interpretation
After Neo4j locates a starting node, it can follow that node's stored relationships without performing a foreign-key join for every hop. The work still grows with the number of relationships inspected, the number of paths produced, and whether the needed pages are cached. A node with millions of relationships can remain a hotspot.
Choose Neo4j for a path-shaped workload
A path-shaped workload asks how entities are connected, not only which records match a filter. The query shape, consistency boundary, and operational constraints should drive the database choice.
Connections are the answer
Strong fit
Fraud rings, identity resolution, recommendations, network dependencies, authorization paths, and knowledge graphs repeatedly traverse several relationship types.
Mixed access patterns
Possible fit
Catalogs and customer views may benefit from graph traversal while orders, ledgers, or large aggregates remain in systems optimized for those access paths.
Connections add little
Weak fit
Append-only events, wide scans, simple key lookups, blob storage, and high-volume time-series aggregation usually have clearer primary stores.
Validate the decision with representative questions
- Name the starting identity, relationship types, maximum useful depth, and result size for each important query.
- Measure degree distribution, not only average degree. A few supernodes can dominate latency and memory even when the average looks safe.
- Decide which facts Neo4j owns. If another database remains authoritative, define an idempotent change-data path and an acceptable synchronization delay.
- Benchmark production-like graph shape and skew. A graph with the right node count but uniform relationships hides the hardest traversal behavior.
Model the graph from questions and invariants
Graph modeling is the process of turning domain questions into stable node identities, relationship semantics, and integrity rules. Start from the path the application must read or change, not from a mechanical copy of relational tables.
1 Query first
Write the question
State the starting entity, the connection to follow, the terminal entity, and the maximum path depth. Include the latency and freshness requirement.
2 Node boundary
Assign identity
Promote a value to a node when it needs independent identity, many relationships, or a lifecycle. Keep descriptive values as properties.
3 Relationship
Name the fact
Use a specific relationship type and meaningful direction. Put properties on the relationship only when they describe that fact rather than either endpoint.
4 Invariant
Enforce and test
Create identity constraints, load skewed sample data, run the real pattern, and inspect its plan before freezing the model into application APIs.
Use constraints as concurrency controls
A uniqueness constraint on Account.id prevents two concurrent writers from creating different nodes for the same account. MERGE describes the pattern to match or create, but a constraint is what makes domain identity unambiguous under concurrency. Prefer merging one constrained node at a time before creating relationships between bound nodes.
Run the standalone example with node content/entries/technology/neo4j/code/model-and-query.mjs. It checks a small in-memory graph without a database, then prints the parameterized Cypher that a Neo4j driver should execute.
Start selective and bound every traversal
Traversal budgeting is a rough estimate of how many relationships a pattern may inspect before filters and deduplication finish. It exposes the most important query controls: anchor cardinality, degree, path depth, and predicates applied while expanding.
Start as close to 1 as possible
Anchor rows
Use a label plus indexed or constrained identity
degree x pass rate
Branching
Measure percentiles and supernodes, not only the mean
Always set a useful maximum
Depth
One extra hop can multiply the search frontier
EXPLAIN, then PROFILE
Evidence
Compare estimated rows, actual rows, DB hits, and memory
The lab is a planning envelope, not a Neo4j benchmark. Cycles, repeated paths, planner operators, cache state, runtime choice, and data skew change real work. Use it to detect a dangerous query shape, then prove the plan against representative data.
Run node content/entries/technology/neo4j/code/estimate-traversal.mjs 1 20 3 100. The four arguments are anchor rows, average degree, maximum hops, and the percentage of relationships that pass an expansion-time predicate.
Read a Cypher plan in order
- Prefix a query with
EXPLAINto inspect estimated operators without executing it. - Confirm the plan begins with a node index seek or another intentionally small anchor, rather than a broad label scan.
- Trace estimated row growth through each expand, join, aggregation, sort, or shortest path operator.
- Use
PROFILEonly on safe, bounded queries because it executes the query and adds measurement overhead. Compare estimated rows with actual rows and inspect DB hits. - Change one model, predicate, or index decision at a time and retain before-and-after plans with the representative parameters.
Keep transaction retries safe
A Neo4j transaction is an atomic unit of reads and writes. The official drivers can route read and write transaction functions and retry transient failures, so the callback may run more than once even though one successful database transaction commits.
Build the write boundary deliberately
- Pass values as query parameters; do not build Cypher by concatenating user input.
- Put all graph changes that protect one business invariant in the same transaction.
- Make retried callbacks idempotent. Do not send email, charge a card, or mutate shared process state inside a callback that the driver may execute again.
- Read or consume results inside the transaction function instead of returning a live result object after the transaction closes.
- Use stable domain keys and constraints before
MERGE; a broadMERGEpattern can create more of the graph than intended. - Bound transaction time, result size, and memory. Large batch imports should use measured chunks and restartable checkpoints.
executeRead and executeWrite are routing declarations, not authorization controls. Database roles and privileges must still prevent an application identity from changing data it should only read.
Size heap, page cache, and native memory separately
Neo4j memory is an operating envelope, not one cache setting. The page cache holds graph store and native index pages; JVM heap holds query, transaction, and object state; the operating system and native allocations also need explicit headroom.
Store and native indexes
Page cache
Cache the repeatedly traversed working set where practical. Watch page faults and hit behavior after restart, topology movement, and workload shifts.
Transactions and queries
JVM heap
Heap must absorb concurrent query state and transaction changes without disruptive garbage collection. One unbounded query can still consume a dangerous share.
Runtime headroom
Native and OS
Network buffers, JVM overhead, plugins, vector indexes, and the operating system need memory outside the configured heap and page cache.
Latency and recovery
Storage
Fast durable storage affects page faults, checkpoints, transaction logs, backup, and recovery. Memory cannot compensate for an untested storage boundary.
Start with neo4j-admin server memory-recommendation, explicitly configure heap and page cache for self-managed deployments, then tune from measurements. Track query latency and timeouts, transaction memory, heap and GC pauses, page cache faults, checkpoint duration, disk latency, and free space together.
Route around failures without weakening consistency
A Neo4j cluster separates consensus-bearing primaries from asynchronously replicated secondaries. One primary is elected writer for each database; secondaries add read capacity but do not join the commit quorum.
Use the scenarios below to trace normal writes, scaled reads, read-after-write, leader failure, and majority loss. Select a component to inspect its responsibility.
Know what each copy can promise
- Three primaries can keep writes available after one primary fails because the two remaining copies still form a majority. A second failure removes write quorum.
- Secondaries pull transaction logs asynchronously and scale read-only work. They can lag and do not increase write fault tolerance.
- Routing drivers discover readers and the current writer when the application uses a routing URI. Directly pinning all work to one server defeats that behavior.
- Bookmarks carry causal position between dependent transactions. Use them when a read must observe a prior write; unnecessary cross-session bookmark dependencies add waiting and coordination.
- Replicas are not backups. They can copy an accidental delete or corrupt logical change. Keep independent backups and prove restore time and recovered state.
Operate the graph from user-visible objectives
Production operations connect graph-specific signals to latency, correctness, availability, and recoverability. A healthy process is not enough if a traversal is silently expanding millions of paths or a cluster has lost write quorum.
Observe one query from admission to durable state
Each stage needs a limit, a signal, and an owner.
Admission
Driver pool
Bound sessions and concurrent transactions, set acquisition and transaction timeouts, and distinguish pool wait from server execution time.
Query work
Planner and runtime
Capture query fingerprints, latency percentiles, rows, DB hits, memory, timeouts, and plan changes for important patterns.
Data path
Store and cache
Watch page cache faults, disk latency, checkpoint pressure, transaction logs, store growth, and hotspots in node degree.
Authority
Cluster
Monitor writer identity, primary health, replication progress, elections, routing errors, and whether a majority remains available.
Proof
Recovery
Run scheduled backups, validate artifacts, restore into an isolated environment, and measure actual RPO, RTO, permissions, constraints, and application-level integrity.
Review before production
- Constraints enforce every domain identity relied on by
MERGEand ingestion. - Critical queries have representative
EXPLAINandPROFILEevidence, bounded path depth, realistic result limits, and tests against high-degree nodes. - Driver pools, transaction retries, timeouts, and backpressure are measured under peak concurrency and during leader changes.
- Least-privilege roles, encrypted client and cluster traffic, credential rotation, and audit requirements match the threat model.
- Memory leaves room for page cache, heap, native allocations, the operating system, maintenance, and failover load.
- Backup restore and cluster failover exercises prove the recovery objectives; they are not inferred from replication status.
Keep the final decision explicit
Neo4j earns its place when bounded traversal is a primary access path and the team can operate a graph-specific consistency and memory model. Keep another store authoritative when the graph is only a derived projection, and define synchronization behavior as part of the product contract.
Correct abstraction
Model for paths
Name identities and relationships from real questions. Protect identity with constraints and treat high-degree nodes as a deliberate modeling decision.
Predictable work
Budget expansion
Seek a selective anchor, specify relationship types, prune during traversal, cap depth, limit results, and verify the physical plan.
Production ownership
Prove recovery
Use routing and bookmarks for the required consistency, monitor quorum and lag, and restore independent backups on a schedule.