FishMem

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 / history surface 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/web

Configure env and secrets

Bindings live in wrangler.toml; secrets are set with wrangler secret put. The required variables:

VariableTypeDescription
OPENAI_API_KEYsecretLLM + embedding provider key.
AUTH_SECRETsecretSigning secret for dashboard sessions.
DBD1 bindingThe graph store database.
VECTORIZEVectorize bindingThe vector index.
R2R2 bindingObject storage bucket.

Set the secrets:

wrangler secret put OPENAI_API_KEY
wrangler secret put AUTH_SECRET

Declare the bindings in wrangler.toml:

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"

Run migrations

Apply the schema to your D1 database:

pnpm run migrate

Deploy to Workers

pnpm run deploy

Wrangler 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.

Next steps

On this page