# SQLite as Local Persistent Cache (Redis-like) for Agentic Workloads
## Purpose
Use SQLite as a **fast, local, persistent cache + state layer** for long-running agentic tasks.
This replaces Redis for:
- single-machine execution
- low ops overhead
- durability (resume after crash)
- debuggability (inspect DB directly)
---
## When to Use
Use SQLite if:
- Single machine / local agent
- Need persistence across restarts
- Dataset ≤ few million rows
- Moderate concurrency (not heavy multi-writer)
Avoid if:
- High concurrent writes across processes
- Need sub-millisecond latency at scale
---
## Core Design
### Table: cache
```sql
CREATE TABLE cache (
cache_key TEXT PRIMARY KEY,
value BLOB,
namespace TEXT,
expires_at INTEGER,
created_at INTEGER,
updated_at INTEGER
);CREATE INDEX idx_namespace ON cache(namespace);
CREATE INDEX idx_expires ON cache(expires_at);SELECT value FROM cache
WHERE cache_key = ?
AND (expires_at IS NULL OR expires_at > ?);INSERT INTO cache (cache_key, value, namespace, expires_at, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT(cache_key) DO UPDATE SET
value = excluded.value,
expires_at = excluded.expires_at,
updated_at = excluded.updated_at;DELETE FROM cache WHERE expires_at IS NOT NULL AND expires_at < ?;- Key:
tool:{tool_name}:{hash(input)} - Value: JSON result
- TTL: short (minutes/hours)
- Key:
run:{run_id}:step:{step_id} - Value: state snapshot
- TTL: none
- Key:
memory:{agent_id}:{topic} - Value: structured JSON
- TTL: long / none
- Key:
lock:{resource} - Value: owner_id
- TTL: short
- Table:
queue - Use status column (
pending,processing,done)
Run once per connection:
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;
PRAGMA temp_store=MEMORY;
PRAGMA cache_size=-20000; -- ~20MB- DO NOT open/close per query
- Reuse a single connection per process
- Avoid dynamic SQL
- Use parameter binding
- Always query by
cache_keyor indexed fields
- Store JSON as BLOB/TEXT
- Avoid querying inside JSON
- Group inserts/updates in transactions
| Operation | Latency |
|---|---|
| Primary key read | ~1–2 ms |
| Indexed read | ~2–5 ms |
| Write | ~2–10 ms |
For 100K records → trivial load
SQLite has no native TTL.
Implement manually:
- Always check
expires_aton read - Run periodic cleanup (cron / background thread)
For ultra-fast access:
memory cache (dict / diskcache)
↓ miss
SQLite
Use this for:
- LLM responses
- repeated tool outputs
- WAL allows concurrent reads + single writer
- Avoid many parallel writers
- Use retry logic on
database is locked
-
Store DB locally:
./agent_state.db
-
Backup if needed
-
Can be inspected manually via CLI
sqlite3 agent_state.db
SELECT * FROM cache LIMIT 10;SQLite gives you:
- Redis-like API (get/set/ttl patterns)
- Persistence
- Low latency (~1–5 ms)
- Zero infra
Best fit for: → local agent → long-running tasks → recoverable execution → structured caching + state
Recommended stack:
SQLite = durable cache + state
(optional) in-memory = hot cache