Why Neo4j? Graph memory architecture
A graph represents stored memory as connected records. This is useful when the application needs to follow relationships between conversations, entities, and recorded actions as well as search their contents.
Graph storage is a design choice with tradeoffs. It does not make every query constant-time or establish that another database cannot express the same question.
The storage problem
Memory retrieval often combines several questions: which records resemble the current query, which entity they describe, when they were recorded, and what other records are connected to them.
Relational databases can represent these relationships through keys and joins. A dedicated vector store can retrieve similar content and apply supported metadata filters. A graph makes the relationships explicit and traversable within the same data model. The choice depends on the application’s actual queries and operating requirements, rather than a universal database ranking.
What a graph makes explicit
Relationships are part of the data model. A conversation can contain messages; messages can mention entities; traces can point back to the messages that triggered them. This helps an application retain provenance instead of reducing everything to disconnected text fragments.
Here is a conceptual read-only query for the Bolt memory schema (see Bolt and NAMS). It requires stored messages with :MENTIONS edges and the parameter $entityName:
MATCH (conversation:Conversation)-[:HAS_MESSAGE]->(message:Message)
MATCH (message)-[:MENTIONS]->(entity:Entity {name: $entityName})
RETURN conversation.session_id, message.content, message.timestamp
ORDER BY message.timestamp DESC
LIMIT 20
The pattern states the relationship being followed. Its cost still depends on the starting lookup, indexes, record counts, node degree, filters, and query plan. Bounding a traversal helps control work; high-degree nodes and long paths can still produce many candidates.
Neo4j also supports vector and temporal data, so an application can combine content similarity with relationships and dates. A schema change may still require validation, index changes, data migration, and updated queries; flexible labels do not remove those responsibilities.
One graph for three memory layers
A single graph can hold conversation history, entities, and task records together. Keeping cross-layer links in one store reduces the need for application-managed joins across separate systems. It also concentrates operational concerns such as indexing, capacity, backup, and access control in that store.
Graph analytics may require an additional capability such as Neo4j Graph Data Science; it is not a guarantee that every Neo4j installation or NAMS endpoint exposes every algorithm. See Backend capabilities.
Example domain: financial services
A financial application may connect a customer to accounts, transactions, and documents, while linking a recommendation to its recorded inputs and tools. The value is the ability to inspect those connections and their provenance.
This is an application-owned domain model, not a set of financial nodes automatically created by the memory library. Legal entities, account holders, and subsidiaries need distinct identities where appropriate. The application remains responsible for authorization and for interpreting the evidence returned by a query.
Example domain: retail
A retail application may connect a product to its variants, inventory locations, and mentions in conversations. A recommendation can then consider both relevant conversational context and application-owned catalog facts.
A product family is not interchangeable with a specific SKU. Keep variant identity and inventory ownership explicit rather than merging similar names. The library’s extraction output does not create a complete product catalog or guarantee that a recommendation meets stock and delivery constraints.
Evaluating performance and capacity
This documentation does not provide a reproducible PostgreSQL-versus-Neo4j benchmark for the proposed workloads. No measured latency, storage estimate, or universal asymptotic comparison is implied here.
Evaluate the queries the application will actually run against representative data. Record database versions, schema and indexes, node and relationship distributions, vector dimensions, concurrency, cache state, and the exact query. Compare equivalent outputs and report latency together with resource use.
Capacity planning must include properties, embeddings, indexes, transaction logs, and operational headroom. Base record sizes alone do not predict a deployment’s disk or memory requirements.
When another storage design fits
A key-value store may be sufficient when memory is only keyed session state. A relational design can fit an existing transactional model with known joins. A dedicated vector store may fit retrieval dominated by similarity search with few graph relationships.
A graph becomes more useful as the application needs to retain and query connections across records. Consider that benefit alongside operational experience, query complexity, and the backend features actually available.