Memory Plugin
The Memory Plugin provides fast, in-memory data storage for your Routier application.
Quick Navigation
- Overview
- Installation
- Basic Usage
- Configuration
- Performance Characteristics
- Use Cases
- API Reference
- Next Steps
Overview
The Memory Plugin is the fastest storage option in Routier, storing all data in RAM for instant access. It's perfect for development, testing, and high-performance applications.
Installation
npm install @routier/memory-pluginBasic Usage
import { DataStore } from "@routier/datastore";
import { s } from "@routier/core/schema";
import { MemoryPlugin } from "@routier/memory-plugin";
const userSchema = s
.define("users", {
id: s.string().key().identity(),
email: s.string().distinct(),
name: s.string(),
createdAt: s.date().default(() => new Date()),
})
.compile();
class Ctx extends DataStore {
users = this.collection(userSchema).proxy().create();
constructor() {
super(new MemoryPlugin("app"));
}
}
const ctx = new Ctx();
await ctx.users.addAsync({ name: "James", email: "[email protected]" });
await ctx.saveChangesAsync();Configuration
Constructor Parameters
import { MemoryPlugin } from "@routier/memory-plugin";
const memoryPlugin = new MemoryPlugin(
"my-app" // Database name (optional). Omit it to use the shared default database.
);Database Name
The database name identifies the database, the same way a file path identifies a SQLite database. Use a distinct name for separate data, and reuse a name deliberately when stores should share data. If you omit the name, the plugin uses a fixed default name, so every unnamed instance shares one database. See Shared Named Databases.
import { DataStore } from "@routier/datastore";
import { MemoryPlugin } from "@routier/memory-plugin";
// Different names are different databases
const userContext = new DataStore(new MemoryPlugin("users"));
const orderContext = new DataStore(new MemoryPlugin("orders"));
// The same name is the same database: records saved through one store are visible to the other
const tabOne = new DataStore(new MemoryPlugin("app"));
const tabTwo = new DataStore(new MemoryPlugin("app"));Performance Characteristics
Advantages
- Instant access - No I/O delays
- High throughput - Can handle thousands of operations per second
- Low latency - Sub-millisecond response times
- No serialization overhead - Data stays in memory
Limitations
- Memory usage - All data must fit in RAM
- No persistence - Data is lost when application restarts
- No cross-process sharing - Separate processes, workers, and browser tabs each hold their own databases, even with the same name. Within one process, instances with the same name share data (see Shared Named Databases)
Use Cases
Development and Testing
import { DataStore } from "@routier/datastore";
import { MemoryPlugin } from "@routier/memory-plugin";
// Perfect for unit tests
class TestContext extends DataStore {
constructor() {
super(new MemoryPlugin("test"));
}
}High-Performance Applications
import { DataStore } from "@routier/datastore";
import { MemoryPlugin } from "@routier/memory-plugin";
// For applications requiring maximum speed
class PerformanceContext extends DataStore {
constructor() {
super(new MemoryPlugin("performance"));
}
}Offline-First with Sync
import { MemoryPlugin } from "@routier/memory-plugin";
import { PouchDbPlugin } from "@routier/pouchdb-plugin";
import { ReplicationDbPlugin } from "@routier/core/plugins";
const memoryPlugin = new MemoryPlugin("offline");
const pouchDbPlugin = new PouchDbPlugin("remote");
const replicationPlugin = new ReplicationDbPlugin({
replicas: [memoryPlugin],
source: pouchDbPlugin,
read: memoryPlugin,
});API Reference
Constructor
import { MemoryPlugin } from "@routier/memory-plugin";
new MemoryPlugin(databaseName?: string)
// Constructor
// @param databaseName - Name of the in-process database to connect to. Instances with the same
// name share one database. Defaults to "__routier-memory-plugin-db__", so
// every unnamed instance shares the same default database.Properties
databaseName- The name of the database
Methods
The Memory Plugin implements all standard plugin methods:
add()- Add entities to collectionsupdate()- Update existing entitiesremove()- Remove entitiesquery()- Query collectionsdestroy()- Clear the named database
Shared Named Databases
The name addresses a database; it is not a label for the plugin instance. The plugin keeps one database per NAME, shared by every MemoryPlugin instance in the same JavaScript process. This is intended, and it mirrors how other databases work: two plugins pointing at the same SQLite file or PostgreSQL database are two connections to the same data.
- Same name, same data - Two
new MemoryPlugin("app")instances read and write the same records. A different name is a different, empty database. - Unnamed instances share too -
new MemoryPlugin()uses a fixed default name, so every unnamed instance connects to the same default database. - Reads are copies - Each store gets its own copies of records, never shared object references. Only saved changes cross stores: an unsaved edit in one store is invisible to another, and mutating a returned object without saving does not change stored data.
- Live queries follow the database - A subscription in one store updates when another store saves to the same-named database.
destroy()affects every instance - It clears the named database for every user of that name, not only for the instance you call it on.- One process only - Separate processes, workers, and browser tabs hold separate databases.
Sharing a name is how you model several stores on one database, such as the tabs of a multi-tab app in a single test. When tests should not see each other's data, give each test its own database name:
const store = new AppStore(new MemoryPlugin(`test-${crypto.randomUUID()}`));Next Steps
- Local Storage Plugin - Browser storage plugin
- File System Plugin - Node.js file storage
- Plugin Architecture - Creating custom plugins