Model or dataset
rush-db/rushdb avatar
rush-db/rushdb

RushDB: a graph plus vector layer that infers schema from raw JSON

RushDB is a graph + vector database and memory layer for AI agents. Push any JSON, get typed, searchable, relationship-aware records back — no schema, no migrations. Built on Neo4j.

323 stars26 forksTypeScriptLicense varies

At a glance

What is it?
RushDB stores JSON records in Neo4j, derives labels and relationships from the shape of the data, and exposes graph traversal and vector search through one API. It is aimed at agent memory and app backends where nobody wants to design a schema first.
Who is it for?
Adopt RushDB if your records arrive as arbitrary JSON and you want graph traversal and semantic recall without running a separate vector store, a separate graph store, and glue code between them. Do not adopt it if you need a stable relational schema with foreign key constraints, or if you are unwilling to operate Neo4j, since the self-hosted path requires your own instance.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The three-database problem RushDB is built to collapse

The README frames the target problem directly: an agent that needs memory usually gets Redis for key-value state, a vector store for semantic recall, and a graph database for relationships, plus synchronization code to keep the three consistent. RushDB's claim is that one API covers all three. The audience is narrow and identifiable: teams building agent memory, RAG pipelines, or application backends where the incoming data is JSON of unpredictable shape. The pitch that matters is not the query language. It is the absence of a schema design step. If your team already has a settled relational model with migrations under review, RushDB solves a problem you do not have.

Inference on write: nested keys become labels, containment becomes an edge

The mechanism described in the README is inference at write time. When you push nested JSON, each nested key becomes a label, each object inside it becomes a record, and the containment becomes a relationship. The COMPANY example makes this concrete: a DEPARTMENT array under a company, an EMPLOYEE array under each department, and the result is three label types with edges between them, created without any edge declaration. There is no migration step because there is no declared schema to migrate. The trade-off is implicit in that design. Inference is a heuristic over your payload, so the graph you get is whatever the shape of your JSON implies. If two different payloads use the same key for different things, or if your real relationships do not line up with nesting, the inferred graph will not match your mental model. The README does not describe a way to override inference or declare an edge explicitly, so this is the first thing to probe with your own data.

Getting it running: two paths, different amounts of work

The cloud path is short. Install the SDK with npm install @rushdb/javascript-sdk or pip install rushdb, then construct a client with an API key: new RushDB('RUSHDB_API_KEY'). The self-hosted path is described as Docker plus your own Neo4j instance, which means the operational surface is Neo4j's, not RushDB's alone. The README links to a self-hosting section but the supplied excerpt does not include its contents, so the exact compose file, environment variables, and version constraints for Neo4j cannot be confirmed here. Treat that as a gap to close before you plan a deployment: read the self-hosting documentation and confirm which Neo4j versions are supported. The client surface is small. Records are written with db.records.create and bulk-loaded with db.records.importJson or db.records.importCsv. Queries go through db.records.find and db.records.vectorSearch.

Vector search without an embedding pipeline

The feature that separates RushDB from a plain graph wrapper is server-side embedding. You register the property once, with await db.ai.indexes.create({ label: 'MEMORY', propertyName: 'output' }), and from then on every write to that property is embedded. The README's agent memory example stores an action with agent_id, session_id, action, topic, and output, and never constructs a vector array. Recall then combines both query types in one call: db.records.vectorSearch takes labels, propertyName, query, a where filter, and a limit, so a semantic query can be scoped by a graph property such as agent_id. That combination is the part worth evaluating. Doing it yourself means querying the vector store for candidates, then filtering or joining against the graph store, and handling the case where the filter removes most of the candidates. The cost of the managed approach is that embedding behaviour lives on the server. The README does not state which embedding model is used, whether you can choose one, or how the index behaves when the property is updated rather than written once. Those are questions for the documentation, not assumptions.

CSV import and the type-suggestion option

CSV ingestion is handled by db.records.importCsv, which takes a label, the raw CSV string, an options object, and a parseConfig. Two options are documented. suggestTypes infers numbers, booleans, and dates from string values, which matters because CSV carries everything as text. skipEmptyValues treats blank cells as unset rather than storing an empty value, and the README notes that 0 and false are preserved rather than dropped. That last detail is the kind of thing that silently corrupts analytics if it is wrong, so it is worth verifying against your own files, particularly columns where an empty cell and a zero mean different things. The parseConfig accepts header: true. Nothing in the supplied material describes how importCsv handles quoted fields containing delimiters, multi-line values, or character encoding, so test those before pointing it at production exports.

Aggregation, and the limit trap the README warns about

Queries support analytical shapes through select and groupBy. Aggregations available are $sum, $avg, $count, $min, and $max, with $precision controlling decimal places on averages. Two examples are given: a portfolio rollup returning one row with totalBudget, avgBudget, and projectCount, and a breakdown grouped by $record.status returning one row per status. The README states a specific constraint: do not add limit to an aggregation, because it would scan only the first N records and skew the totals. It also notes that orderBy is applied late so that aggregates cover the full dataset. That is a real footgun. A limit clause that looks like a performance optimisation silently changes the meaning of a sum. The documentation calls it out, which is good, but there is no compiler or runtime error to stop you. Aggregations compose with traversal, and the README points at a payroll-per-department example, though the excerpt is truncated mid-query at the $alias token, so the full traversal syntax for that case cannot be reproduced here.

Where RushDB is the wrong tool

The absence of a schema is the product, and it is also the limitation. There is no migration step, which means there is also no migration artifact you can review, diff, or roll back. If your application depends on a column being present and correctly typed for every row, inference at write time gives you no guarantee of that. A malformed payload produces a record with a different shape, and the database accepts it. Teams under regulatory or audit requirements that demand a documented data model should look elsewhere. The dependency on Neo4j is the second constraint. Self-hosting means operating a graph database, including its memory tuning and backup story, which is a larger commitment than running a single container. The cloud path removes that, at the cost of sending your data to a managed service. Neither path is described in the supplied material as offering a way to bring your own embedding model, so if embedding choice is a hard requirement, confirm that before evaluating further.

The alternative: assembling the three stores yourself

The honest alternative is the stack RushDB is positioned against: Neo4j for relationships, a dedicated vector store for semantic search, and Redis or similar for key-value state, joined by application code. The difference is not performance, it is where the complexity sits. In the assembled stack you own the synchronization logic, you choose the embedding model, and you can tune each store independently. You also get to keep the vector index when you swap the graph layer, and vice versa. In RushDB the three concerns are one API and one deployment, which is less code to write and less to keep consistent, but it also means you cannot replace one layer without replacing the client. If your workload is graph-heavy and semantic search is a small part of it, a plain Neo4j deployment with a vector index may cover you with one fewer abstraction. If semantic search dominates and relationships are incidental, a purpose-built vector store is the simpler choice. RushDB is for the case where both are first-class and you want them in one query.

Maintenance, versioning, and the licence question

The repository ships several independently versioned packages. The most recent listed releases are @rushdb/mcp-server at 2.13.0, @rushdb/skills at 2.12.0, and @rushdb/agent-memory-contract at 0.2.0. The zero-major version on agent-memory-contract means its API can change without a major version bump, so pin it if you depend on it. The mcp-server package indicates an MCP integration path, which is relevant if your agent runtime speaks that protocol, though the supplied material does not describe its configuration. On licensing: the README badge points to Apache 2.0 and links to packages/javascript-sdk/LICENSE, while the repository metadata given here lists the licence as unknown. Those two signals disagree. Before you ship, open the LICENSE file in the specific package you install and confirm it, and check whether the server component carries the same terms as the SDK. This is not legal advice; it is a discrepancy you should resolve by reading the file.

Editorial conclusion

Adopt RushDB if your records arrive as arbitrary JSON and you want graph traversal and semantic recall without running a separate vector store, a separate graph store, and glue code between them. Do not adopt it if you need a stable relational schema with foreign key constraints, or if you are unwilling to operate Neo4j, since the self-hosted path requires your own instance. Before committing, verify three things in your own environment: how the automatic relationship inference behaves on your nested payloads, whether the vector search latency under your embedding volume is acceptable, and what the licence terms are for the specific package you install, because the repository metadata does not state one.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. rush-db/rushdb on GitHub
Community notes

Community notes