Stop wasting tokens and speed up Claude Code: implementing offline memory for LLM agents
I'm Denis Shokhirev, Enterprise AI architect based in Erlangen, Germany. At DennisCraft AI Studio, I ship AI systems for DACH B2B clients using a stack of Claude, Supabase, n8n, Doppler, and self-hosted Postgres. Over the last six months, I've deployed 14 production AI agents—and every time, I've run into the same real-world pain: token costs spiral, latency creeps up, and Claude Code eats budget as fast as GPT-4. Why offline memory is critical in production Every time your Claude Code-based
I'm Denis Shokhirev, Enterprise AI architect based in Erlangen, Germany. At DennisCraft AI Studio, I ship AI systems for DACH B2B clients using a stack of Claude, Supabase, n8n, Doppler, and self-hosted Postgres. Over the last six months, I've deployed 14 production AI agents—and every time, I've run into the same real-world pain: token costs spiral, latency creeps up, and Claude Code eats budget as fast as GPT-4.
Why offline memory is critical in production
Every time your Claude Code-based LLM agent needs context, it re-ingests the entire interaction history in the prompt. This isn't just expensive: on multi-step workflows, responses slow down and you quickly hit the context window limit. In sectors like logistics or fintech, where SLAs require responses within 2-3 seconds, this approach simply isn't viable.
Across three recent production agent launches, I measured 18–27% token waste due to redundant data sent in every request. If you're running RAG or complex automations, the problem multiplies.
Structuring offline memory: what works in production
Storage: Postgres vs Supabase
I've tested both. Supabase is quick for prototyping, but for SLA-driven use cases, self-hosted Postgres consistently beats it on latency and control. For caching intermediate states (state, task history, embeddings), I create a dedicated table:
CREATE TABLE agent_memory (
agent_id UUID,
session_id UUID,
step_number INT,
input_payload JSONB,
output_payload JSONB,
created_at TIMESTAMP DEFAULT NOW()
);Index on agent_id and session_id for fast lookups.
Access layer: n8n or direct API
If your orchestration runs on n8n, you can connect directly via the Postgres node. For more complex read/write logic, I recommend a dedicated FastAPI or Node.js backend with endpoints for reading/writing memory.
# FastAPI endpoint to save agent memory
from fastapi import FastAPI, Request
import asyncpg
app = FastAPI()
pool = None
@app.on_event("startup")
async def startup():
global pool
pool = await asyncpg.create_pool(dsn="postgresql://user:pass@localhost/db")
@app.post("/memory")
async def save_memory(request: Request):
data = await request.json()
async with pool.acquire() as conn:
await conn.execute(
"INSERT INTO agent_memory (agent_id, session_id, step_number, input_payload, output_payload) VALUES ($1, $2, $3, $4, $5)",
data["agent_id"], data["session_id"], data["step_number"], data["input_payload"], data["output_payload"]
)
return {"status": "ok"}Test with real data—latency for 1000+ insert/retrieve ops should stay below 50–70ms.
Integrating with Claude Code: minimizing token usage
Context selection
Instead of sending the entire history in every prompt, I only fetch relevant steps via SQL queries or simple embedding-based filters. For semantic similarity, pgvector works well:
SELECT * FROM agent_memory
ORDER BY embedding <#> '[0.12, 0.33, ...]' LIMIT 3;The result: only the last 2–3 steps and the most relevant prior cases are included in the prompt—token usage drops by double digits.
Automating with n8n
n8n lets you build a stable pipeline: receive input → fetch memory by session_id → construct prompt → call Claude Code. For SLA-driven scenarios, I add an extra step: if latency exceeds 1s, the prompt is trimmed to only the minimal necessary context.
| Storage Method | Latency (ms/1000 ops) | Control | Production Maturity |
|---|---|---|---|
| Supabase | 90–120 | Medium | Great for prototypes |
| Self-hosted Postgres | 50–70 | Maximal | Recommended for production |
Memory security: what you can't skip
LLM agents generate and store data that may include sensitive info (PII, finance, logs). I always run automated leak checks using bandit and gitleaks, following OWASP Top 10 patterns. On one project, bandit flagged 4 unsafe evals in agent-generated code out of 5000 records.
gitleaks detect --source . --report-path=leaks.json
bandit -r ./src -f json -o bandit_report.jsonAt a minimum, encrypt input_payload/output_payload fields. For DACH, you often need DSGVO compliance: never store raw, unanonymized PII.
FAQ
Which DB should I use for offline memory?
For production, self-hosted Postgres is the stable choice. Supabase is fine for MVPs but introduces higher latency and less control.
How do I cut token waste on long histories?
Only send relevant steps in the prompt—use embeddings to fetch similar cases. Never include the full history unless strictly required.
What's the best stack for Claude Code integration?
n8n for orchestration, Postgres for memory, FastAPI/Node.js for the API layer, and bandit/gitleaks for security. This setup is proven across 10+ production agents.
How do I test pipeline latency?
Generate 1000+ ops, measure average read/write times before and after optimization. Compare Supabase to self-hosted Postgres under load.
What’s the minimum for DACH compliance?
Encrypt payloads, anonymize PII, and document all memory handlers for audit readiness.
Where in your LLM agent pipeline do memory issues hit hardest—latency, token waste, or data leaks? I’m happy to review your setup. I offer a free 30-min stack audit for DACH teams building AI for regulated markets. DM me on LinkedIn or at @ger_dennis_ai.
Turn your process into an AI system
Fixed price. Production quality. DACH B2B focus.