A fast, SQLite-backed key-value cache for Bun. No Redis required.
- Zero dependencies - Uses Bun's built-in SQLite
- Persistent storage - Data survives restarts
- TTL support - Automatic expiration with lazy + periodic cleanup
- Atomic operations -
incr/decrare transaction-safe - Batch operations -
mget/mset/mdelfor bulk operations - Type-safe - Full TypeScript support
bun add quickvimport { Cache } from "quickv";
const cache = new Cache();
// Basic operations
cache.set("user:1", { name: "Alice", email: "[email protected]" });
const user = cache.get<User>("user:1");
// With TTL (in seconds)
cache.set("session:abc", sessionData, 3600); // 1 hourconst cache = new Cache({
path: "./cache.db", // Default: ":memory:" (in-memory)
cleanupInterval: 60_000, // Default: 60000ms (1 min). Set to 0 to disable.
});| Method | Description |
|---|---|
set(key, value, ttl?) |
Store a value with optional TTL in seconds |
get<T>(key) |
Retrieve a value. Returns undefined if not found or expired |
del(key) |
Delete a key |
has(key) |
Check if a key exists and is not expired |
| Method | Description |
|---|---|
ttl(key) |
Get remaining TTL in seconds. Returns undefined if missing, null if no expiry |
expire(key, ttl) |
Set/update expiry. Pass null to remove expiry. Returns false if key doesn't exist |
cache.incr("views"); // 1
cache.incr("views"); // 2
cache.incr("views", 5); // 7
cache.decr("views"); // 6Both preserve existing TTL on the key.
// Set multiple values
cache.mset({ a: 1, b: 2, c: 3 }, ttl?);
cache.mset(new Map([["a", 1], ["b", 2]]));
cache.mset([["a", 1], ["b", 2]]);
// Get multiple values
const values = cache.mget<number>(["a", "b", "c"]); // Map<string, number>
// Delete multiple keys
cache.mdel(["a", "b"]);| Method | Description |
|---|---|
keys(pattern?) |
List keys. Supports * and ? wildcards |
size() |
Count of non-expired entries |
clear() |
Delete all entries |
cleanup() |
Manually remove expired entries. Returns count removed |
close() |
Close database and stop cleanup timer |
cache.set("user:1", "alice");
cache.set("user:2", "bob");
cache.set("post:1", "hello");
cache.keys("user:*"); // ["user:1", "user:2"]
cache.keys("*:1"); // ["user:1", "post:1"]// In-memory (default) - fastest, lost on restart
const cache = new Cache();
// File-based - persists across restarts
const cache = new Cache({ path: "./cache.db" });SQLite WAL mode is enabled automatically for better concurrent performance.
Benchmarked on Apple M4 Pro:
~600,000 writes/sec
~1,650,000 reads/sec
Use quickv when:
- Single Bun instance
- Need persistent caching without external dependencies
- Want Redis-like API with zero setup
Use Redis when:
- Multiple instances need shared cache
- Need pub/sub or streams
- Distributed systems
MIT