@frontmcp/storage-sqlite provides a local storage backend for FrontMCP using SQLite. It replaces Redis for single-process deployments where you need persistence without managing external infrastructure.
Zero Infrastructure
No Redis or external database needed — just a local file
Persistent Sessions
Sessions, elicitation state, and SSE events survive restarts
Optional Encryption
AES-256-GCM at-rest encryption via HKDF-SHA256
WAL Mode
Write-Ahead Logging enabled by default for better read concurrency
When to Use SQLite
Installation
Quick Start
With Unix Socket (Recommended)
The simplest way to use SQLite is via thesqlite option on FrontMcpInstance.runUnixSocket():
With @FrontMcp Decorator
Configuration Options
The database location can also be supplied through the
FRONTMCP_SQLITE_PATH environment variable (used by frontmcp start --db, frontmcp socket --db and the generated installer). It overrides sqlite.path; other sqlite options are kept.Encryption
Enable at-rest encryption to protect stored session data. Keys are stored in plaintext (needed for lookups); only values are encrypted.- Your secret is run through HKDF-SHA256 to derive a 256-bit key
- Each value is encrypted with AES-256-GCM using a random 96-bit IV
- Stored format:
base64url(iv):base64url(tag):base64url(ciphertext)
Store Types
@frontmcp/storage-sqlite provides three specialized stores, all built on a common SqliteKvStore:
Session Store
Stores MCP session data with TTL support.Event Store
Stores SSE events for resumability with max event limits and TTL-based eviction.Elicitation Store
Stores pending elicitation requests with EventEmitter-based single-process pub/sub.Comparison: SQLite vs Redis vs Vercel KV
Troubleshooting
Error: Cannot find module 'better-sqlite3'
Error: Cannot find module 'better-sqlite3'
Cause: The If you’re using yarn with PnP, you may need to add it as a dependency (not devDependency).
better-sqlite3 native module is not installed.Solution:SQLITE_CANTOPEN: unable to open database file
SQLITE_CANTOPEN: unable to open database file
Cause: The parent directory is created for you, so this means the path itself cannot be opened: no permission to create the directory, a path that points at a directory or a file that is not a database, or a read-only file system.Solution: Check the permissions and that
path names a file. Serverless targets with a read-only file system need a writable path such as /tmp, or a different store.Database is locked
Database is locked
Cause: Multiple processes are trying to write to the same SQLite file simultaneously.Solution: The store sets
busy_timeout (5 s by default) before it enables WAL and creates tables, and retries SQLITE_BUSY during startup, so two processes starting on the same file wait for each other. If a writer holds the lock longer than that, raise busyTimeoutMs. SQLite still allows one writer at a time: for many writer processes, use Redis.Encryption errors after changing the secret
Encryption errors after changing the secret
Cause: Existing data was encrypted with a different secret.Solution: Reading a value written under another secret throws
SqliteDecryptionError (code SQLITE_DECRYPTION_FAILED) with a message that names the secret as the likely cause. Restore the original secret or delete the database file and let the server create a fresh one. There is no migration path between encryption keys.Related Documentation
Unix Socket
Run FrontMCP as a persistent local server over Unix sockets
Redis Setup
Configure Redis for multi-instance production deployments
Vercel KV
Edge-compatible storage for Vercel deployments
Runtime Modes
Compare SDK, Server, and Handler deployment modes