Forcing an AI coding agent to re-read your entire codebase every time you start a new session is the fastest way to drain your API budget and degrade response quality.
- Token consumption (annual): ~170K (retrieval) vs. ~19.5M (full-context)
- Ideal tech stack: SQLite + FTS5 (full-text search)
- Performance benchmark: 95.2-95.4% Recall@5 on LongMemEval, from a hierarchical retrieval system, not raw keyword search in isolation
- Cloud vector DB required: no, not until enterprise scaling is needed
Why "Paste Full Context" Ruins Your API Budget
Relying on the sheer size of modern LLM context windows creates a false sense of security. Throwing a massive folder of code into the prompt works for a quick, isolated debugging session, but it completely falls apart for long-term projects. You pay for every single token, read and re-read, across dozens of daily interactions.
Eventually, the agent loses track of your actual prompt inside the overwhelming noise of boilerplate code.
Token Economics: 19.5M vs 170K Annually
That 170K-vs-19.5M comparison comes from a solo developer's real usage logs on a daily coding routine, not a lab benchmark. Treat it as a general rule of thumb rather than a number your setup will hit exactly. The mechanism behind it is straightforward: a smart local agent only loads a tiny, top-level summary on startup to grasp the current state of the project. Detailed technical specs, past bug fixes, and logic decisions get pulled into the context window only when a specific query triggers a search, instead of being included in every prompt.
The Local-First Architecture: SQLite + FTS5
You do not need an expensive cloud vector database to build intelligent, persistent memory. A single SQLite file bundled directly with your agent is more than capable of handling memory for solo developers and small teams.
Using the built-in FTS5 (full-text search) extension provides sub-millisecond query responses. This completely eliminates the heavy computational overhead of generating, storing, and updating vector embeddings for every minor code tweak.
When Full-Text Search Beats Semantic Vector Search
Cloud vector databases shine when you need semantic understanding of vague concepts, but coding agents operate differently. When an agent searches its memory, it usually looks for highly specific, deterministic strings. Searching for a specific function name, a unique variable, or a known error code requires exact keyword matching, not a "semantically similar" approximation.
FTS5 handles this exact matching flawlessly. When your memory stays within the tens of thousands of entries, SQLite easily outperforms remote vector stores simply by eliminating network latency. You keep your entire project history local, entirely private, and lightning-fast.
A minimal schema uses SQLite's external-content pattern: a plain table holds the real rows, and the FTS5 virtual table indexes it by rowid instead of a separate text key.
CREATE TABLE memory_meta (chunk_id INTEGER PRIMARY KEY, file_path TEXT, commit_hash TEXT, updated_at TEXT, content TEXT);
CREATE VIRTUAL TABLE memory_fts USING fts5(content, content='memory_meta', content_rowid='chunk_id');
Querying it for a specific error string is a single line: SELECT chunk_id, file_path FROM memory_fts WHERE memory_fts MATCH 'ECONNREFUSED' ORDER BY rank LIMIT 5; No embedding step, no API call, results in under a millisecond on a local file.
Markdown and Code Chunking Strategies
Dumping raw, unformatted code files into a database ruins the retrieval quality and confuses the agent. You need a structured chunking strategy that respects the syntax and logic of your files.
- Markdown chunking: split your documentation by H2 and H3 headers. This keeps the retrieved context tightly bound to the specific feature being described.
- Code chunking: isolate individual functions, classes, or distinct logical blocks rather than relying on arbitrary line-count splits.
- Metadata tagging: append file paths, commit hashes, and timestamps to each chunk. The agent needs to know exactly which version of the logic it is reading to avoid hallucinating outdated solutions.
Scaling Up: When SQLite Stops Being Enough
SQLite handles thousands of memory fragments without breaking a sweat, but it is not magic. Eventually, an agent managing massive monorepos across dozens of developers will hit a structural wall.
When cross-referencing interconnected services becomes the primary task, pure text search starts to miss the broader architectural context.
Migrating to pgvector and Graph Databases (Neo4j)
You transition to a vector or graph database only when the relationships between codebases matter more than the raw code itself. Production-scale setups often integrate pgvector for deep semantic searches across millions of tokens to find conceptually similar code blocks.
To map out complex dependencies, like understanding how a change in an API gateway affects three downstream microservices, graph databases like Neo4j step in. This transition makes sense for enterprise budgets and complex architectures, but it is expensive overkill for a personal coding assistant.
Building Your Own Memory Framework (Decision Matrix)
Stop overengineering your first AI agent with complex cloud infrastructure. Start small, measure the token burn, and scale the architecture only when retrieval accuracy actually drops. Here is a practical framework to guide your build:
- Phase 1, solo or prototype: bundle a single SQLite file with FTS5. Focus entirely on clean markdown and precise code chunking. Zero cloud costs, instant queries.
- Phase 2, growing project: implement a hybrid local approach. Keep SQLite for exact keyword searches, but generate local embeddings using lightweight, open-source models for semantic backup queries.
- Phase 3, team scale: move to a dedicated backend with pgvector and Neo4j. Use this strictly to map complex entity relationships and handle massive concurrent memory reads across a team.
The first version of my own agent memory setup skipped straight to embeddings because that's what every tutorial assumed you needed. Every retrieval added an embedding API round-trip before the agent could even start reasoning, and for queries like "where did I handle the ECONNREFUSED retry logic," a plain keyword match against the function name would have returned the right chunk instantly. For that exact class of query, ripping out the vector layer and querying FTS5 directly cut retrieval latency from a few hundred milliseconds to sub-millisecond.
Deciding which coding agent to build this around matters less than deciding the memory layer first. It's the piece that determines whether your setup gets cheaper or more expensive as your codebase grows.
