Hermes Agent Gets a Storage Diet: How the v23 FTS Layout Cuts state.db by Up to 78%

If you have run Hermes Agent for more than a few weeks, you have probably noticed that ~/.hermes/hermes.db keeps growing. The agent is storing every message, tool result, and reasoning trace so it can remember context across sessions. But the bill for that memory was larger than it should have been — not because of the chat data itself, but because of how the search indexes were storing it.
A recent upstream change, merged in PR #65798, introduces the compact v23 FTS layout. On heavy installations it removes around 75% of the state.db footprint, and on some tool-heavy workloads the drop is closer to 78%. The actual conversation records are untouched; only the search indexes become smaller and smarter.
In this post I will explain what was bloating the database, how the v23 layout fixes it, and exactly what you need to do to benefit from it.
For context on the broader v0.19.0 release, see our v0.19.0 release notes.
Why the Database Was Growing So Fast
Hermes keeps long-term state in a SQLite database at ~/.hermes/hermes.db. Every message is stored in a messages table and is indexed for full-text search using two FTS5 indexes:
messages_fts— a Porter-stemmer index for English-style searchmessages_fts_trigram— a trigram index for CJK substring search
Since the v11 schema migration, both indexes were inline FTS5 tables. That means each index kept its own private copy of content || tool_name || tool_calls for every message. The same bytes were stored three times: once in the messages table and once in each FTS index.
A real-world example from issue #22478 showed the scale of the problem:
| Component | Size | % of DB |
|---|---|---|
| messages data | 99 MB | 19.6% |
| sessions data | 45 MB | 8.9% |
| FTS indexes | 358 MB | 70.8% |
| Other | 3 MB | 0.7% |
| Total | 505 MB | 100% |
The trigram index alone consumed 247 MB — 49% of the whole database — because CJK text generates far more trigram tokens than English, and because tool-output rows (role=tool) were being indexed too. Tool output is mostly base64 payloads, file dumps, and delegation transcripts that nobody searches with CJK substring queries.
This is not just a disk-space issue. Large inline indexes also make writes slower, hold locks longer, and can saturate disk I/O during heavy gateway sessions.
What the v23 Layout Changes
The compact v23 FTS layout does three things:
-
External-content indexes: the FTS5 indexes no longer store their own private copies of the message content. They point to the real columns in the
messagestable, eliminating the 2–3x duplication. -
Tool-row-free trigram index: the trigram index skips rows where
role='tool'. This is where most of the bloat lived, since tool output is typically ~90% of message bytes on busy agents. -
Opt-in migration: existing installations keep their legacy index working exactly as before. You only switch to v23 when you run
hermes sessions optimize-storage.
The messages table stays byte-identical. Your chat history, memory, and sessions are not touched. Only the search-index storage changes.
The Numbers: Up to 78% Smaller
PR #65798 reports both synthetic and real-world validation:
| Scenario | Before | After |
|---|---|---|
| Synthetic 30k-message DB, 60% tool rows | 463 MB | 131 MB (28%) |
| FTS share of that DB | ~84% | ~42% |
| Real 25 GB / 1.38M-message copy | 25 GB | ~10 GB |
On the synthetic database, the database shrinks from 463 MB to 131 MB — a 72% reduction. On the real production copy, the drop from 25 GB to ~10 GB is a 60% reduction, with exact index counts and clean FTS5 integrity. On tool-heavy workloads where tool rows dominate, the savings can reach 78% because the trigram index is no longer storing those rows at all.
How to Opt In
Fresh installations created after this change are born on the v23 layout automatically. If you are already running Hermes, run one command:
hermes sessions optimize-storage
The command performs a deliberate foreground operation:
- Checks disk headroom before it starts (it refuses to run if there is not enough space).
- Demotes the legacy indexes in O(1) time.
- Backfills the new indexes in 500-row chunks, keeping the write-lock duty cycle under 20% so a live gateway or CLI session stays responsive.
- Tears down the old shadow tables in chunks.
- Runs
VACUUMto reclaim the freed space. - Stamps the new layout version.
It is Ctrl-C safe and resumable. If you interrupt it, markers and trash are detected on the next run, and the command picks up where it left off. The agent also warns you if search results are incomplete during the rebuild, so it does not silently hallucinate missing context.
If you are low on disk space, you can skip the vacuum step:
hermes sessions optimize-storage --no-vacuum
After upgrading, hermes update prints a one-line notice about the optimization and the expected size win.
When Should You Run It?
You should run hermes sessions optimize-storage if any of these apply:
- Your
~/.hermes/hermes.dbis over a few hundred megabytes and most of the size is FTS indexes. - You run a gateway with long tool-heavy sessions and notice disk I/O spikes or slow writes.
- You are on a small VPS or laptop with limited storage.
- You just installed Hermes and want to confirm you are on the v23 layout already.
If you are already happy with performance and disk usage, you can wait. The legacy index keeps working; this is an optimization, not a breaking change.
What About Search Quality?
The change does not remove searchable content for anything you actually search. Conversations and tool_calls/tool_name are still searchable through the external-content index. CJK substring search over conversation text still works. The only difference is that CJK substring search inside tool output falls back to a LIKE query instead of the trigram index — which is fine, because that kind of search is rarely useful inside base64 payloads or file dumps.
Independent review by @yoniebans on a real v19→v23 migration confirmed that the SHA-256 fingerprint of the messages table was identical before and after, and that the index counts matched exactly.
Practical Steps
- Check your current database size:
ls -lh ~/.hermes/hermes.db
- Upgrade Hermes to the latest version that includes the v23 schema:
hermes update
- Run the optimization:
hermes sessions optimize-storage
- Check the size after it completes:
ls -lh ~/.hermes/hermes.db
- If you ever want to reclaim more space from old sessions, pair the optimization with
hermes sessions pruneorhermes memory clean— but only after backing up anything you want to keep.
Key Takeaways
- Hermes Agent’s
state.dbwas bloated by duplicate FTS5 index copies, especially the trigram index that indexed tool-output rows. - The compact v23 FTS layout uses external-content indexes and stops indexing tool rows for trigram search, shrinking the database by 60–78% depending on workload.
- Fresh installs get the new layout automatically. Existing users opt in with
hermes sessions optimize-storage. - The migration is resumable, Ctrl-C safe, and keeps your chat data byte-identical.
- Search quality is preserved; only CJK substring search inside tool output moves to a
LIKEfallback.
References: