Multi-tenant, high-performance asynchronous cache library for Node.js. Uses a persistent, sharded SQLite backend (WAL mode) with automatic checkpointing and per-key TTL support, offering a drop-in alternative to Redis for many caching scenarios.
npm install @johanlabs/rust-scribaRust Scriba is a multi-tenant cache library written in Rust with Node.js bindings.
It provides a persistent SQLite LRU cache with sharding, TTL support, automatic checkpoints, and easy integration to replace Redis in many scenarios.
---
- Multi-tenant cache with sharding to reduce contention.
- Persistent SQLite backend (WAL mode) with automatic checkpointing.
- Supports TTL per key.
- Asynchronous operations for high performance.
- Drop-in cache replacement for Node.js.
- Benchmark included to compare with Redis.
---
``bash``
npm install @johanlabs/rust-scriba
> Requires Node.js 20+ and Rust (cargo) to build the native module.
---
Before using the cache, initialize the system:
`js
const { initCacheSystem, scribaPath } = require("@johanlabs/rust-scriba");
// Set the base path for tenant databases
scribaPath(".scriba");
// Initialize the cache (automatic checkpointing)
initCacheSystem();
`
---
You can use the Database class to manage tenants and execute queries with caching.
`js
const { Database } = require("@johanlabs/rust-scriba");
const db = new Database("tenant1", { ttl: 10000, path: ".scriba" });
(async () => {
// Run a SELECT and return one row
const row = await db.get("SELECT * FROM my_table WHERE id=1");
console.log(row);
// Run a SELECT and return all rows
const rows = await db.all("SELECT * FROM my_table");
console.log(rows);
// Run an INSERT/UPDATE/DELETE
const result = await db.run("INSERT INTO my_table (name) VALUES ('Alice')");
console.log(result);
})();
`
* db.prepare(sql) → returns a Statement.db.get(sql)
* → returns a JSON object with one row.db.all(sql)
* → returns an array of JSON rows.db.run(sql)
* → executes changes (INSERT, UPDATE, DELETE).db.close()
* → closes the tenant (optional, currently empty).
---
You can also interact with the cache directly:
`js
const { query } = require("@johanlabs/rust-scriba");
// Direct GET/SET
await query("tenant1", "SELECT * FROM my_table", 5000);
`
* query(tenant, sql, ttl_ms?) → returns a Promise containing JSON result.
---
A benchmark is included to compare RustCache against Redis:
`js
const { runBenchmark } = require("@johanlabs/rust-scriba");
(async () => {
const results = await runBenchmark();
console.log(JSON.stringify(results, null, 2));
})();
`
The benchmark measures:
* get and set latency.p50
* Concurrent operations.
* Latency percentiles (, p95, p99).get
* Mixed /set operations.
* Large value handling (100 KB payloads).
---
Global configurations are defined in Rust, but you can adjust constants internally:
* tenant_cache_limit: max items per tenant.global_cache_limit
* : global cache limit.shard_count
* : number of shards per tenant.default_ttl_secs
* : default TTL.checkpoint_interval_secs
* : interval for automatic checkpoints.checkpoint_retry_attempts
* & checkpoint_retry_delay_ms: retry settings for checkpointing.
---
* Each tenant is identified by its tenantId` (typically the DB path).
* TTL is optional and sets cache expiration.
* SQLite persistence ensures data survives restarts.
* Supports asynchronous and concurrent operations with high throughput.