
# RushDB
### The memory layer for AI agents and apps.
Push any JSON. Your agent gets a live, queryable schema, graph relationships, and semantic search β inferred automatically.
No pipeline. No separate stores. No schema to design.
[](https://github.com/rush-db/rushdb)
[](https://x.com/RushDatabase)
[](https://www.npmjs.com/package/@rushdb/javascript-sdk)
[](https://pypi.org/project/rushdb/)
[](packages/javascript-sdk/LICENSE)
[](https://github.com/rush-db/rushdb/actions)
[π Website](https://rushdb.com) β’ [π Documentation](https://docs.rushdb.com) β’ [βοΈ Cloud](https://app.rushdb.com) β’ [π Examples](https://github.com/rush-db/examples)
**English** β’ [δΈζ](README_ZH.md) β’ [ζ₯ζ¬θͺ](README_JA.md) β’ [νκ΅μ΄](README_KO.md) β’ [Deutsch](README_DE.md) β’ [FranΓ§ais](README_FR.md) β’ [PortuguΓͺs](README_PT.md) β’ [EspaΓ±ol](README_ES.md) β’ [ΰ€Ήΰ€Ώΰ€¨ΰ₯ΰ€¦ΰ₯](README_HI.md) β’ [Ψ§ΩΨΉΨ±Ψ¨ΩΨ©](README_AR.md) β’ [Bahasa Indonesia](README_ID.md) β’ [ΰΉΰΈΰΈ’](README_TH.md)
---
## The problem
Your agent needs memory. The standard answer is three databases: Redis for key-value, a vector store for semantic search, a graph DB for relationships β plus glue code to keep them in sync.
RushDB replaces all three. Push JSON once. Query it with graph traversal, semantic search, or both β in one call.
| Without RushDB | With RushDB |
| ----------------------------------------- | -------------------------------------- |
| Redis + Pinecone + Neo4j + glue code | One API |
| Design schema β write migrations β repeat | Push any shape, no schema required |
| Separate embedding pipeline | Managed embeddings, server-side |
| Hand-craft relationship edges | Auto-detected from your data structure |
---
## Quick start
Two paths depending on your setup:
- **Cloud** β Managed, free tier, running in 30 seconds. [Get API key β](https://app.rushdb.com)
- **Self-host** β Docker + your own Neo4j instance. [Jump to Self-hosting β](#self-hosting)
### Cloud path
```bash
npm install @rushdb/javascript-sdk
# or
pip install rushdb
```
### Store and recall agent memory
```typescript
import RushDB from '@rushdb/javascript-sdk'
const db = new RushDB('RUSHDB_API_KEY')
// One-time: tell RushDB to auto-embed 'output' on every write
await db.ai.indexes.create({ label: 'MEMORY', propertyName: 'output' })
// Store an agent action β no embedder, no vectors array
await db.records.create({
label: 'MEMORY',
data: {
agent_id: 'agent-42',
session_id: 'sess-001',
action: 'summarized',
topic: 'Q4 results',
output: summaryText
}
})
// Recall by meaning β graph filter + semantic search in one call
const memories = await db.records.vectorSearch({
labels: ['MEMORY'],
propertyName: 'output',
query: 'what did we decide about Q4?',
where: { agent_id: 'agent-42' },
limit: 10
})
```
```python
from rushdb import RushDB
db = RushDB('RUSHDB_API_KEY')
# Store β graph links sessions, actions, and context automatically
db.records.create(
label='MEMORY',
data={
'agent_id': 'agent-42',
'action': 'summarized',
'topic': 'Q4 results',
'output': summary_text,
},
)
# Recall β traverse relationships and filter by meaning
results = db.records.find({
'labels': ['MEMORY'],
'where': {
'agent_id': 'agent-42',
'topic': {'$contains': 'Q4'},
},
'limit': 10,
})
```
---
## Working with your data
### Import nested JSON
Push any JSON shape. Nested objects and arrays of objects become linked records β labels, types, and relationships are inferred on write. No schema, no migration step.
```typescript
await db.records.importJson({
label: 'COMPANY',
data: {
name: 'Acme Corp',
DEPARTMENT: [
{
name: 'Engineering',
budget: 2_000_000,
EMPLOYEE: [
{ name: 'Alice', role: 'Staff Engineer', salary: 210_000 },
{ name: 'Bob', role: 'Engineer', salary: 160_000 }
]
}
]
}
})
```
Each nested key (`DEPARTMENT`, `EMPLOYEE`) becomes a label, each object a record, and containment a relationship β all created automatically.
### Import CSV
```typescript
const csv = `name,email,department
Alice,alice@acme.co,Engineering
Bob,bob@acme.co,Sales`
await db.records.importCsv({
label: 'EMPLOYEE',
data: csv,
options: { suggestTypes: true, skipEmptyValues: true },
parseConfig: { header: true }
})
```
`suggestTypes` infers numbers, booleans, and dates from strings; `skipEmptyValues` treats blank cells as unset instead of storing empty values (`0` and `false` are kept).
### Traverse the graph
Filter root records by conditions on their _related_ records β arbitrarily deep β in a single query. Related labels go **inside** `where`, not in `labels`:
```typescript
// Engineers in Acme's Engineering department
const engineers = await db.records.find({
labels: ['EMPLOYEE'],
where: {
role: { $contains: 'Engineer' },
DEPARTMENT: {
name: 'Engineering',
COMPANY: { name: 'Acme Corp' }
}
}
})
```
### Analytical queries (aggregate & group by)
`select` shapes the output with aggregations (`$sum`, `$avg`, `$count`, `$min`, `$max`); `groupBy` controls the dimensions. Don't add `limit` to an aggregation β it would scan only the first N records and skew the totals.
```typescript
// Portfolio KPIs across ALL projects β one row
const kpis = await db.records.find({
labels: ['PROJECT'],
select: {
totalBudget: { $sum: '$record.budget' },
avgBudget: { $avg: '$record.budget', $precision: 2 },
projectCount: { $count: '*' }
},
groupBy: ['totalBudget', 'avgBudget', 'projectCount'],
orderBy: { totalBudget: 'asc' } // late-ordering β aggregates the full dataset
})
// β [{ totalBudget: 18_750_000, avgBudget: 568181.82, projectCount: 33 }]
// Breakdown by dimension β one row per status
const byStatus = await db.records.find({
labels: ['PROJECT'],
select: { count: { $count: '*' }, avgBudget: { $avg: '$record.budget', $precision: 2 } },
groupBy: ['$record.status'],
orderBy: { count: 'desc' }
})
// β [{ status: 'active', count: 18, avgBudget: 612000 }, { status: 'paused', count: 9, ... }]
```
Aggregations compose with traversal β e.g. headcount and payroll per department:
```typescript
const payroll = await db.records.find({
labels: ['DEPARTMENT'],
where: { EMPLOYEE: { $alias: '$emp' } }, // alias the related node for use in select
select: {
headcount: { $count: '*' },
payroll: { $sum: '$emp.salary' }
},
groupBy: ['$record.name'],
orderBy: { payroll: 'desc' }
})
// β [{ name: 'Engineering', headcount: 2, payroll: 370000 }, ...]
```
---
## Connect to Claude, Cursor, or any MCP client
RushDB ships an MCP server. Your agent gets persistent, structured memory β out of the box.
```json
{
"mcpServers": {
"rushdb": {
"command": "npx",
"args": ["@rushdb/mcp-server"],
"env": {
"RUSHDB_API_KEY": "your-api-key-here"
}
}
}
}
```
Place this in your Claude Desktop, Cursor, or Windsurf MCP config. The agent can now create records, search by meaning, traverse relationships, and introspect the schema β all via natural language.
---
## What's in the box
| Capability | What it means |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Managed embeddings** | Index any string property once β every write is auto-embedded server-side |
| **Graph + vector in one query** | Semantic similarity and relationship traversal compose in a single call |
| **Zero schema** | Push any JSON shape. RushDB infers types, creates properties, links records |
| **Inferred schema** | Properties become first-class nodes β types, labels, and relationships are discovered on write, so a queryable schema builds itself as data arrives |
| **ACID transactions** | Concurrent agents don't corrupt shared memory. Neo4j under the hood |
| **Self-describing** | Agents introspect the inferred schema β labels, properties, value ranges β to know what they can safely query |
| **MCP-native** | Full MCP server with discovery-first query prompt built in |
| **Agent Skills** | Installable `@rushdb/skills` package β teach any skills-compatible agent to query, model, and remember with RushDB in one command |
| **Unified query API** | One JSON shape for graph, vector, aggregation, and introspection |
| **Self-host or cloud** | Docker + your Neo4j, or managed cloud. Full data ownership |
---
## Use cases
| Use case | What RushDB replaces | Key API |
| --------------------------- | ------------------------------- | ------------------------------------------------------------- |
| **Agent memory** | Redis + vector store + graph DB | `db.records.vectorSearch({ query, where: { agent_id } })` |
| **RAG with context** | Flat vector store | `db.records.find({ where, labels })` + relationship traversal |
| **Schema-free apps** | Postgres + migrations + ETL | `db.records.importJson(nestedJson)` |
| **Connected data products** | Multiple joined services | `db.records.find({ labels, where: { SOME_LABEL: { ... } } })` |
---
## Self-hosting
> **Self-host path** β run RushDB on your own infrastructure. Requires Neo4j 2026.01.4+ with APOC plugin.
```yaml
# docker-compose.yml
version: '3.8'
services:
rushdb:
image: rushdb/platform
ports:
- '3000:3000'
environment:
- NEO4J_URL=neo4j+s://your-instance.neo4j.io
- NEO4J_USERNAME=neo4j
- NEO4J_PASSWORD=password
- RUSHDB_AES_256_ENCRYPTION_KEY=32-char-key-here
- RUSHDB_LOGIN=admin
- RUSHDB_PASSWORD=secure-password
# Optional: managed continuous-sync connectors via synx
- RUSHDB_BASE_URL=https://rushdb.example.com
- RUSHDB_SYNX_CONTROL_TOKEN=long-random-shared-token
- RUSHDB_SYNX_DESTINATION_API_KEY=internal-write-api-key
```
Full environment variables
| Name | Description | Required | Default |
| --------------------------------- | ---------------------------------------------- | ---------- | -------- |
| `NEO4J_URL` | Neo4j connection URL | yes | β |
| `NEO4J_USERNAME` | Neo4j username | yes | neo4j |
| `NEO4J_PASSWORD` | Neo4j password | yes | β |
| `RUSHDB_AES_256_ENCRYPTION_KEY` | 32-char key for API token encryption | yes (prod) | β |
| `RUSHDB_PORT` | HTTP port | no | 3000 |
| `RUSHDB_LOGIN` | Admin login | no | admin |
| `RUSHDB_PASSWORD` | Admin password | no | password |
| `RUSHDB_BASE_URL` | Public/base API URL for synx assignments | no | β |
| `RUSHDB_SYNX_CONTROL_TOKEN` | Internal token for managed synx workers | no | β |
| `RUSHDB_SYNX_DESTINATION_API_KEY` | Internal write key for synx destination writes | no | β |
Managed synx workers run as daemons. They poll for runnable connectors, renew connector leases, release leases on graceful shutdown, and let platform/core reclaim expired leases after crashes.
Local development (bundled Neo4j)
```yaml
version: '3.8'
services:
rushdb:
image: rushdb/platform
depends_on:
neo4j:
condition: service_healthy
ports:
- '3000:3000'
environment:
- NEO4J_URL=bolt://neo4j
- NEO4J_USERNAME=neo4j
- NEO4J_PASSWORD=password
neo4j:
image: neo4j:2026.01.4
healthcheck:
test: ['CMD-SHELL', 'wget --no-verbose --tries=1 --spider localhost:7474 || exit 1']
interval: 5s
retries: 30
start_period: 10s
ports:
- '7474:7474'
- '7687:7687'
environment:
- NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
- NEO4J_AUTH=neo4j/password
volumes:
- ./neo4j-plugins:/var/lib/neo4j/plugins
```
```bash
# Manage users via CLI
rushdb create-user admin@example.com securepassword123
rushdb update-password admin@example.com newsecurepassword456
```
Architecture: how RushDB structures data (LMPG)
RushDB uses a **Labeled Meta Property Graph (LMPG)** model. Properties are elevated to first-class graph nodes ("HyperProperties") β not just key-value pairs attached to records.
This means:
- **Schema without upfront design** β because properties are graph nodes, the schema is _inferred from your data, not designed_: labels, types, value ranges, and relationship topology are discovered on write and queryable immediately β no manual schema modeling, no RDF/OWL toolchain
- **Auto-detected relationships** β records sharing properties get linked without hand-crafting edges
- **Schema introspection** β agents can enumerate labels, property types, value ranges, and relationship topology in one query
- **Soft constraints** β type cohesion scoring, cardinality tracking, and vector dimension enforcement without rigid upfront schemas
- **Unified query surface** β the same filter expression works across records, labels, properties, and relationships
One SearchQuery retrieves multiple perspectives simultaneously (records + property stats + aggregations), avoiding the N+1 inspection pattern common in separate-system architectures.
[Read the full LMPG architecture post β](https://rushdb.com/blog/labeled-meta-property-graphs-rushdb-s-revolutionary-approach-to-graph-database-architecture)
---
## Documentation
| Topic | Link |
| ------------------------ | -------------------------------------------------------------- |
| Quick Tutorial | https://docs.rushdb.com/get-started/quick-tutorial |
| Vector / Semantic Search | https://docs.rushdb.com/concepts/search/where#vector-operators |
| Filtering & Traversal | https://docs.rushdb.com/concepts/search/where |
| Grouping & Aggregations | https://docs.rushdb.com/concepts/search/group-by |
| TypeScript SDK | https://docs.rushdb.com/typescript-sdk/introduction |
| Python SDK | https://docs.rushdb.com/python-sdk/introduction |
| REST API | https://docs.rushdb.com/rest-api/introduction |
| MCP Server | packages/mcp-server/README.md |
| Agent Skills | packages/skills/README.md |
---
## When not to use RushDB
- You need sub-millisecond latency at very high write throughput β RushDB is built on Neo4j, which prioritises consistency and query expressiveness over raw write speed.
- You only need flat key-value storage with no relationships or semantic search β a simpler store will be lighter.
- You need a rigid relational schema enforced at the database level β RushDB is deliberately schema-free.
---
## Contributing
```bash
git clone https://github.com/rush-db/rushdb.git
cd rushdb
pnpm install
pnpm test
```
See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines. Issues and PRs welcome.
---
## License
| Path | License |
| ----------------------- | ------------------- |
| platform/core | Elastic License 2.0 |
| platform/dashboard | Elastic License 2.0 |
| docs | Apache 2.0 |
| website | Apache 2.0 |
| packages/javascript-sdk | Apache 2.0 |
| packages/mcp-server | Apache 2.0 |
---
Need something not supported yet? Open an issue β design discussions are welcome.