Skip to content
Contextely
Academy8 min readBy The Contextely Team

Self Hosted Agent Memory: Lessons Learned in Prod

What actually breaks running self hosted agent memory for months: backup, re-indexing, cost creep, monitoring, and the on-call gotchas nobody documents.

A rack of servers in a server room, standing in for the self hosted agent memory infrastructure that needs backup, monitoring and re-indexing once it is running real traffic

Photo: Kevin Ache on Unsplash

Key takeaways

Running a demo of self hosted agent memory takes an afternoon. Running one for eight months, through a re-indexing job that ran long, a database restore nobody had rehearsed, and a bill that crept up without anyone noticing, is a different exercise entirely. This is what we learned doing the second one, not the first.

Most write-ups of self-hosted memory stacks stop at the docker compose file. That is fair; a setup guide has to stop somewhere. But the setup is the easy 20%. The other 80% is what this post covers: backup strategy, what actually needs monitoring, where cost creeps in, and the operational gotchas that only show up once real traffic and real time have passed.

What a self hosted agent memory stack actually looks like in production

Strip away the marketing and a self-hosted memory layer for AI agents is usually three moving parts: a Postgres database holding condensed records (sometimes with a vector column via pgvector, sometimes with embeddings stored as plain JSONB and matched in application code), a background worker that condenses raw source data into summaries, and an API or MCP surface agents actually call. Mem0's self-hosted server, for example, packages exactly this shape: a FastAPI server, Postgres with pgvector for embeddings, and Neo4j for entity relationships, all as separate containers you run yourself.

None of that is exotic. What is easy to miss is that two of those three parts run continuously, unattended, and unless you designed limits into them, they will happily consume a weekend's worth of compute or a month's LLM budget without complaining. The database is the part everyone remembers to back up. The jobs around it are the part that actually breaks.

Stage Typical effort What usually gets skipped
Initial setup (containers, first source) A few hours Nothing, this part is well documented everywhere
First month of real traffic A few hours a week Setting a hard ceiling on re-index and refresh concurrency
Month two to six An afternoon a month, until it isn't Testing a restore, not just taking a backup
Month six onward Ongoing, spikes on incidents Watching LLM spend per source, not just total spend

Table 1: where operational effort actually lands over the life of a self-hosted memory deployment, not where the setup guides spend their word count.

How do you back up a self hosted agent memory database?

The same way you back up any Postgres database, and that is exactly the trap. A memory store built from condensed summaries has no independent source of truth once it exists. The original ticket, contract or Slack thread might still be retrievable from its system of record, but the condensed version, the one your agents actually query, exists only in that one database. Lose it without a backup and you are not restoring stale data, you are starting from zero.

"Continuous backup can be achieved simply by continuing to archive the WAL files. This is particularly valuable for large databases, where it might not be convenient to take a full backup frequently."
PostgreSQL documentation, Continuous Archiving and Point-in-Time Recovery

Continuous WAL archiving plus a periodic base backup is the standard answer, and it is genuinely enough for most memory deployments, because the write volume from condensation is modest compared to a transactional application. The part teams skip is not setting up the backup. It is testing the restore. A backup that has never been restored is a hope, not a plan, and the failure mode for a memory layer specifically is quiet: nothing crashes, agents just start answering from nothing.

The embedding re-indexing gotcha nobody warns you about

If you turn on semantic ranking over a self-hosted embedding column, whether that is a proper vector type through pgvector or a simpler JSONB-plus-cosine approach some products use to avoid a hard extension dependency, you have added a second background job class: re-indexing and re-embedding whenever the underlying content changes enough to matter.

The first time we let embedding re-indexing run unattended over a weekend, it did not fail. It just did not stop. Nobody had set a concurrency limit on it, so it queued every source's refresh at once, the LLM provider's rate limit started queuing requests behind it, and by Monday morning the condensation pipeline for ordinary new records was backed up behind a weekend of re-embedding work that had nothing urgent about it. The fix was not clever. It was a hard cap on concurrent embedding jobs and a rule that re-indexing runs at a lower priority than fresh ingestion, so a maintenance task can never starve the thing agents are actually waiting on.

pgvector's own guidance is blunt about the underlying reason: an index built with the IVFFlat or HNSW methods degrades as the underlying vectors change, and a healthy deployment schedules REINDEX INDEX CONCURRENTLY and routine vacuuming rather than assuming the index stays optimal forever. That maintenance has a cost in database load, and if nobody put a ceiling on when it runs, it competes directly with live retrieval traffic at the worst possible moment.

What should you monitor in a self hosted memory stack?

Four things, and none of them are the ones a generic uptime check gives you for free:

Where the cost actually creeps in

Self-hosted software has no seat licence, which is the headline and also slightly misleading. The running cost of a memory layer is not the container, it is the LLM calls behind condensation and, if enabled, embedding, and both scale with volume and refresh frequency rather than with a flat fee. A source with a six-hour freshness window that could tolerate a daily one is paying for four times the re-condensing it needs, every day, silently, until someone checks the per-source cost line rather than the total.

The comparable pattern shows up in a fuller cost breakdown of running your own MCP governance layer, in self-hosted MCP governance cost: the software is free, the ongoing bill is compute plus a usage-priced dependency, and the gap between "free to run" and "cheap to run" is entirely in how carefully those knobs are set, not in which product you picked.

The gotcha that has nothing to do with your infrastructure

Not every operational risk is something your team did. Some of it is upstream. Zep announced it was discontinuing its open source Community Edition, moving its self-hosted open-source effort onto a different project entirely and leaving the old code in an unmaintained legacy state.

"We've decided to stop maintaining and releasing Zep Community Edition. The existing repository will remain open under the Apache 2.0 license, but we will no longer provide updates or active support."
Zep, announcing the change to its open source strategy

Nothing about that decision was a bug or an outage. It is the ordinary risk of building on someone else's open source roadmap: the project you picked for self hosted agent memory can simply stop being a project, and the difference between an inconvenience and a real incident is whether your team could keep running the last supported version indefinitely, patched and understood, or whether you were depending on upstream activity that has now stopped. Before adopting any self-hosted memory project, it is worth reading its issue tracker for the last three months rather than only its README, because that tells you whether you are joining a maintained tool or inheriting one.

A practical operational checklist

Risk Mitigation
Database loss with no tested restore Continuous WAL archiving plus a quarterly restore drill onto a throwaway instance
Re-indexing or refresh jobs run unbounded Hard concurrency caps, and re-indexing at lower priority than fresh ingestion
Cost creep from over-aggressive TTLs Per-source cost monitoring, reviewed monthly, not just a total spend alert
Upstream project abandonment Check commit and issue activity before adopting; keep a pinned, patchable fork plan
Stale data served silently Per-source freshness alerting, not a single global health check

Table 2: the operational risks that show up after month two of running a memory layer, and what closes each one.

Self hosted versus managed, honestly

None of the above is an argument against self-hosting. It is an argument for pricing in the operational work honestly before choosing it. A self hosted ai memory setup guide gets you a running stack in an afternoon; this post is about the months after that afternoon, and that gap is exactly the trade a managed option is priced against. If your team wants a graph-first, developer-controlled alternative to build this pipeline around, the Cognee comparison covers that shape of tool and its own trade-offs in more detail.

Contextely's own self-hosted path runs on the same honest terms described here: Postgres, a container, and your own LLM key, with condensation failing loudly rather than silently guessing when that key is wrong. Its retrieval ranking is term-overlap by default, with optional semantic ranking an operator can turn on rather than something assumed to already be running, and when embeddings are stored at all they live as JSONB scored with in-process cosine rather than a dedicated vector extension, a decision made specifically to avoid a hard dependency the schema cannot ship without. Whether that trade-off or a fully custom stack fits your team better is worth comparing on the pricing page against what a few months of the checklist above actually costs to run yourselves.

Frequently asked questions

The honest answer to most of the questions above is "it depends on how much of this checklist you were already planning to build," which is not a satisfying sentence but is the accurate one. What holds up regardless of which memory stack you pick is the shape of the risk: backup that has never been restored is not a backup, a background job without a ceiling will eventually find the ceiling for you, and a project's roadmap is not yours to control once you have built on top of it.

Frequently asked questions

Is self hosted agent memory harder to run than a normal database?

The database part is not the hard part. Postgres with a JSONB or vector column behaves like any other Postgres. The hard part is the background jobs around it: condensation, freshness refresh and re-indexing, none of which show up in a docker compose file until they misbehave.

What breaks first when you self host agent memory in production?

Usually backup, because it is invisible until the day it is needed. A stack that has been condensing records for months and has no tested restore procedure is one disk failure away from having no memory at all, not degraded memory.

How much does self hosting agent memory actually cost after the first month?

The compute is usually the cheap part. The line that grows is LLM usage for condensation and, if you turn it on, embedding calls, both of which scale with how much you ingest and how often you refresh it, not with a fixed licence fee.

Can you self host both Mem0 and Zep, and is one easier to keep alive?

Mem0 self hosted ships as three containers, a FastAPI server, Postgres with pgvector, and Neo4j, which you operate yourself. Zep self hosted is a more fragile bet: the company discontinued its open source Community Edition, so anyone running it is now maintaining an unsupported fork rather than a live project.

Do you need Kubernetes to run a self hosted memory layer reliably?

No. A single well-monitored host with proper backups covers most teams under a few hundred users. Kubernetes buys you replica failover, which is rarely the actual failure mode; the failure mode is a silent backup gap or an unbounded background job, and neither is solved by adding orchestration.

Free for 500 retrievals a month, and self-hostable with no limits.