Self-hosted dashboard
Run the FishMem control-plane — dashboard, API keys, usage, webhooks, and the mem0-compatible API — on your own Cloudflare account.
The fishmem engine is a library you
embed. This page is about the layer above it: the control-plane, the full
application that wraps the engine with a UI and a REST surface. It ships as the
apps/web app in the open-source
fishmem-labs/fishmem repo, and is the
same app that powers FishMem Cloud.
If you only need memory inside one service, self-host the engine instead — see Self-hosting the engine. Run the control-plane when you want a team-facing platform.
What it provides
- A web dashboard to manage projects, keys, and memories.
- API key management — issue and revoke
fm_...keys per project. - A usage view over operations and storage.
- Webhooks that fire on memory events.
- The mem0-compatible REST API — the same
add/search/get/update/delete/historysurface documented in the API reference.
It runs on Cloudflare: a Worker serves the SSR dashboard and the API (via OpenNext), D1 holds the graph store, Vectorize holds the vector index, and R2 holds object storage. The only thing it leaves out compared to the managed cloud is managed billing and SLA.
Run it
Prerequisites
- A Cloudflare account with Workers enabled.
- A D1 database, a Vectorize index, and an R2 bucket in that account.
- An LLM provider key (a
gpt-4o-mini-class model) and an embedding provider key (text-embedding-3-small). - Node.js and the Wrangler CLI installed locally.
Clone the repo
git clone https://github.com/fishmem-labs/fishmem
cd fishmem
pnpm install
cd apps/webConfigure env and secrets
Bindings live in wrangler.toml; secrets are set with wrangler secret put.
The required variables:
| Variable | Type | Description |
|---|---|---|
OPENAI_API_KEY | secret | LLM + embedding provider key. |
AUTH_SECRET | secret | Signing secret for dashboard sessions. |
DB | D1 binding | The graph store database. |
VECTORIZE | Vectorize binding | The vector index. |
R2 | R2 binding | Object storage bucket. |
Set the secrets:
wrangler secret put OPENAI_API_KEY
wrangler secret put AUTH_SECRETDeclare the bindings in wrangler.toml:
[[d1_databases]]
binding = "DB"
database_name = "fishmem"
database_id = "<your-d1-id>"
[[vectorize]]
binding = "VECTORIZE"
index_name = "fishmem"
[[r2_buckets]]
binding = "R2"
bucket_name = "fishmem"Deploy to Workers
pnpm run deployWrangler prints the deployed URL. The dashboard is served at the root; the
mem0-compatible API is under /v1.
Create your first project and API key
Open the deployed URL, sign in, create a project, and issue an API key from the dashboard. Then call your own instance exactly like the hosted cloud:
curl https://<your-worker>.workers.dev/v1/memories \
-H "Authorization: Bearer fm_..." \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "I prefer dark mode."}],
"user_id": "alex"
}'Self-hosting the control-plane gives you the same engine, dashboard, and API as FishMem Cloud. The difference is operations: the managed cloud handles billing, scaling, and updates for you and offers an SLA. Self-hosting means you run the Cloudflare resources, apply migrations on upgrade, and meter usage yourself.