Memory Storage
The @graphrag-js/memory package provides in-memory and file-based storage for development, testing, and small-scale production use.
Installation
pnpm add @graphrag-js/memoryThe memory package is included by default with @graphrag-js/core.
Features
- ✅ Zero external dependencies - No database required
- ✅ Fast performance - Sub-millisecond operations
- ✅ File persistence - Optional JSON file storage
- ✅ Simple setup - Perfect for development and testing
- ✅ Full feature support - Implements all storage interfaces
Storage Options
In-Memory Storage
All data stored in RAM. Fast but not persistent across restarts.
import { createGraph } from '@graphrag-js/core';
import { memoryGraph, memoryVector, memoryKV } from '@graphrag-js/memory';
import { openai } from '@ai-sdk/openai';
const graph = createGraph({
model: openai('gpt-4o-mini'),
embedding: openai.embedding('text-embedding-3-small'),
storage: {
graph: memoryGraph,
vector: memoryVector,
kv: memoryKV,
}
});File-Based Storage (Persistent)
Data persists to JSON files on disk.
import { jsonGraph, jsonKV, memoryVector } from '@graphrag-js/memory';
const graph = createGraph({
model: openai('gpt-4o-mini'),
embedding: openai.embedding('text-embedding-3-small'),
storage: {
graph: jsonGraph('./data/graph.json'),
vector: memoryVector, // No file persistence for vectors yet
kv: jsonKV('./data/kv.json'),
}
});API Reference
memoryGraph(namespace)
Creates an in-memory graph store using Cytoscape.js.
import { memoryGraph } from '@graphrag-js/memory';
const graphStore = memoryGraph('my-namespace');Features:
- Node and edge CRUD operations
- Connected components clustering
- BFS/DFS traversal
- Knowledge graph extraction
- Cytoscape.js algorithms
Implementation: Uses Cytoscape.js headless mode for graph operations.
memoryVector(namespace)
Creates an in-memory vector store with cosine similarity search.
import { memoryVector } from '@graphrag-js/memory';
const vectorStore = memoryVector('my-namespace');Features:
- Multiple distance metrics (cosine, euclidean, dotproduct)
- Metadata filtering
- Index management
- In-memory CRUD operations
Implementation: Pure TypeScript implementation with manual similarity calculations.
memoryKV(namespace)
Creates an in-memory key-value store using JavaScript Map.
import { memoryKV } from '@graphrag-js/memory';
const kvStore = memoryKV('my-namespace');Features:
- Fast lookups (O(1))
- Field filtering
- Batch operations
- Simple Map-based storage
Implementation: JavaScript Map with JSON serialization support.
jsonGraph(filepath)
Creates a file-persisted graph store.
import { jsonGraph } from '@graphrag-js/memory';
const graphStore = jsonGraph('./data/graph.json');Features:
- Automatic file persistence
- GraphML export/import
- Same API as memoryGraph
- Load on startup, save on changes
File Format: GraphML (XML-based graph format)
jsonKV(filepath)
Creates a file-persisted key-value store.
import { jsonKV } from '@graphrag-js/memory';
const kvStore = jsonKV('./data/kv.json');Features:
- Automatic file persistence
- JSON format
- Same API as memoryKV
- Load on startup, save on changes
File Format: JSON
Usage Examples
Basic Setup
import { createGraph } from '@graphrag-js/core';
import { similarityGraph } from '@graphrag-js/similarity';
import { memoryGraph, memoryVector, memoryKV } from '@graphrag-js/memory';
import { openai } from '@ai-sdk/openai';
const graph = createGraph({
model: openai('gpt-4o-mini'),
embedding: openai.embedding('text-embedding-3-small'),
provider: similarityGraph(),
storage: {
graph: memoryGraph,
vector: memoryVector,
kv: memoryKV,
}
});
await graph.insert('Your documents here...');
const result = await graph.query('Your question?');With File Persistence
import { jsonGraph, jsonKV, memoryVector } from '@graphrag-js/memory';
const graph = createGraph({
model: openai('gpt-4o-mini'),
embedding: openai.embedding('text-embedding-3-small'),
storage: {
graph: jsonGraph('./data/graph.graphml'),
vector: memoryVector, // Still in-memory
kv: jsonKV('./data/chunks.json'),
}
});Multi-Tenant Setup
const tenant1 = createGraph({
namespace: 'tenant-1',
storage: {
graph: memoryGraph,
vector: memoryVector,
kv: memoryKV,
}
});
const tenant2 = createGraph({
namespace: 'tenant-2',
storage: {
graph: memoryGraph,
vector: memoryVector,
kv: memoryKV,
}
});
// Completely isolated storagePerformance
Benchmarks
Operations on 10,000 nodes/vectors (M1 Mac):
| Operation | memoryGraph | memoryVector | memoryKV |
|---|---|---|---|
| Insert | 0.1ms | 0.05ms | 0.01ms |
| Lookup | 0.05ms | - | 0.01ms |
| Vector Search (k=10) | - | 2-5ms | - |
| Graph Traversal (depth=2) | 1-3ms | - | - |
Memory Usage
Approximate memory usage:
- Graph Node: ~1KB per node
- Vector (1536-dim): ~6KB per vector
- KV Entry: ~0.5-2KB per entry (depends on content)
Example: 10,000 documents with entities:
- ~50,000 nodes × 1KB = 50MB
- ~10,000 vectors × 6KB = 60MB
- ~10,000 chunks × 1.5KB = 15MB
- Total: ~125MB
Limitations
When to Use Memory Storage
✅ Good for:
- Development and testing
- Prototyping and demos
- Small datasets (< 100K documents)
- Single-server deployments
- Fast iteration cycles
❌ Not recommended for:
- Large-scale production (> 100K documents)
- Distributed systems
- High-availability requirements
- Long-running processes with large datasets
- When you need advanced graph algorithms (use Neo4j)
Memory Limits
JavaScript has a default heap size limit:
- Node.js default: ~2GB (32-bit) or ~4GB (64-bit)
- Can increase with
--max-old-space-sizeflag
node --max-old-space-size=8192 your-app.js # 8GB heapMigration to Production
When you outgrow memory storage, migrate to production backends:
// Step 1: Export from memory
const memoryGraph = createGraph({
storage: { graph: memoryGraph, vector: memoryVector, kv: memoryKV }
});
const data = await memoryGraph.export('json');
// Step 2: Create production graph
import { neo4jGraph } from '@graphrag-js/neo4j';
import { qdrantVector } from '@graphrag-js/qdrant';
import { redisKV } from '@graphrag-js/redis';
const prodGraph = createGraph({
storage: {
graph: neo4jGraph({ url: 'bolt://localhost:7687', ... }),
vector: qdrantVector({ url: 'http://localhost:6333', ... }),
kv: redisKV({ host: 'localhost', port: 6379 })
}
});
// Step 3: Import data
await prodGraph.import(data);Best Practices
Development Workflow
- Use memory storage during development for fast iteration
- Add file persistence for local testing
- Switch to production storage for deployment
Testing Strategy
// test/setup.ts
export function createTestGraph() {
return createGraph({
namespace: `test-${Date.now()}`, // Unique per test
storage: {
graph: memoryGraph,
vector: memoryVector,
kv: memoryKV,
}
});
}
// test/my-feature.test.ts
describe('My Feature', () => {
it('should work', async () => {
const graph = createTestGraph();
// Test with clean, isolated storage
});
});Backup Strategy
For file-based storage:
import { jsonGraph, jsonKV } from '@graphrag-js/memory';
import { cpSync } from 'fs';
// Periodic backups
setInterval(() => {
cpSync('./data/graph.json', `./backups/graph-${Date.now()}.json`);
cpSync('./data/kv.json', `./backups/kv-${Date.now()}.json`);
}, 3600000); // Every hourNext Steps
- Neo4j Storage - For large-scale graph operations
- Qdrant Storage - For high-performance vector search
- Redis Storage - For distributed KV storage