Skip to content

Mem0 v1.0 Install Guide: AI Long Term Memory Setup

Deploy Mem0 for AI long term memory in under 10 minutes. Real install commands, the hardcoded 1536-dim Qdrant bug that breaks Ollama, and a Docker self-host walkthrough.

8 min readIntermediate

Every LLM chat starts amnesiac. You tell an agent your deployment preferences on Monday, and by Tuesday it’s asking again. Mem0 is the memory layer most teams reach for when they need AI long term memory without rebuilding a retrieval pipeline from scratch – and this guide walks you through deploying Mem0 v1.0 (tagged October 16, 2025) the way you’d actually run it in production: self-hosted, with the install traps that break most first attempts already flagged.

If you just want the pip SDK talking to the hosted platform, that’s five lines and you don’t need a tutorial. This is for the harder path – the Docker stack you own end to end.

What you’re actually deploying

Three containers, not one. The self-hosted Mem0 server runs FastAPI for the REST layer, PostgreSQL with pgvector for embeddings, and Neo4j for entity relationships. That’s the trade for owning your memory data – two stateful backends to feed and back up, plus the API in front of them.

Why the hybrid? Because raw conversation turns are expensive to retrieve and query. Mem0’s add() call runs an LLM extraction pass first – pulling out facts, preferences, and entities – then distributes those across the three stores. Retrieval returns 4-5 sentences, not a 50-turn transcript. The extraction and consolidation loop is described in the research paper (arXiv:2504.19413, 2025) if you want the mechanism in detail.

Thinking about it like a filing system helps: the vector store is the fuzzy-match drawer (semantic search), the key-value store is the exact-lookup index, and Neo4j is the org chart that links entities to each other. Mem0 decides what goes where. You just call add().

System requirements

Laptop dev works fine – 2 vCPU, 4 GB RAM, about 5 GB disk free, Docker Desktop running. For anything real:

Environment CPU / RAM Disk Notes
Cloud minimum t3.medium (2 vCPU / 4 GB) 20 GB EBS ~$30/month on-demand (as of October 2025) – Neo4j + pgvector + API side by side
Room to breathe t3.large (2 vCPU / 8 GB) 30 GB Steady traffic, or if you’re running Ollama models locally

Software: Python 3.10+, Docker Engine 24+, the Compose plugin. The default LLM provider is OpenAI (gpt-4o-mini as of October 2025 – verify against the current README, as this has changed across minor versions), so you’ll need an OpenAI key unless you’re swapping the embedder and LLM out.

One thing to check before you pull anything: the mem0/mem0-api-server image on Docker Hub is arm64-only. Turns out, amd64 hosts – most EC2 instances, Railway, standard Linux VMs – can’t use it. You build from the GitHub server/Dockerfile instead. Only Apple Silicon and Graviton get the pre-built image.

Install: Docker path

Clone and bootstrap. The make bootstrap target does the heavy lifting – starts the stack, creates an admin account, and issues your first API key in one shot.

git clone https://github.com/mem0ai/mem0.git
cd mem0/server

cp .env.example .env
echo "OPENAI_API_KEY=sk-..." >> .env

make bootstrap

Alternatively: docker compose up -d and finish setup via the browser wizard at http://localhost:3000. Either way, first run pulls ~500 MB of base images – budget 2-5 minutes depending on your connection.

Just want the SDK?

One-liner. No server needed if you’re pointing at the hosted platform:

pip install mem0ai
# Optional NLP extras for spaCy-based entity extraction
pip install "mem0ai[nlp]"
python -m spacy download en_core_web_sm

The mem0ai package on PyPI ships two entry points: Memory for self-hosted deployments, MemoryClient for the hosted platform. Same install, different config.

The dimension trap (read this before you configure anything)

Most tutorials skip this. It’s the single biggest source of failed installs in Mem0’s issue tracker.

Mem0’s default embedding model is OpenAI’s text-embedding-3-small, which outputs 1536-dimensional vectors. That number is hardcoded as a fallback in multiple places – including the Qdrant collection creation logic. Switch to Ollama’s nomic-embed-text (768 dims) or bge-m3 (1024 dims), and Qdrant creates the collection at 1536 anyway. Every add() and search() call fails with a cryptic Bad Request. GitHub issues #4173, #4212, and #4695 all hit the same wall.

The fix: embedding_model_dims must go inside vector_store.config, not embedder.config. Putting it in the embedder block alone doesn’t propagate. Working Ollama + Qdrant config:

from mem0 import Memory

config = {
 "vector_store": {
 "provider": "qdrant",
 "config": {
 "collection_name": "prod_memory",
 "host": "localhost",
 "port": 6333,
 "embedding_model_dims": 768, # MUST match embedder output
 },
 },
 "llm": {
 "provider": "ollama",
 "config": {
 "model": "llama3.1:latest",
 "ollama_base_url": "http://localhost:11434",
 },
 },
 "embedder": {
 "provider": "ollama",
 "config": {
 "model": "nomic-embed-text:latest",
 "ollama_base_url": "http://localhost:11434",
 },
 },
 "version": "v1.1",
}

m = Memory.from_config(config)

Before writing memories, hit your embedder endpoint once with a dummy string and check len(vec). Whatever number comes back is what embedding_model_dims must equal. Skip this and you’ll spend an afternoon debugging a Bad Request with no stack trace pointing at the real cause.

What the 1536 default actually reveals: Mem0 was built OpenAI-first, and the non-OpenAI paths are community-maintained. That’s not a criticism – it’s useful to know before you assume the config schema is symmetric across providers. It isn’t, not yet.

Verify the install

Three checks, in order.

  1. Containers up: docker compose ps – all three services should show healthy. The mem0 container maps to port 8000 (check the ps output for your host mapping).
  2. API reachable: curl http://localhost:8000/docs should return Swagger UI HTML.
  3. Round-trip write and read:
curl -X POST http://localhost:8000/memories 
 -H "Authorization: Bearer $ADMIN_API_KEY" 
 -H "Content-Type: application/json" 
 -d '{
 "messages": [{"role": "user", "content": "I deploy everything on Hetzner and use uv for Python."}],
 "user_id": "dev_01"
 }'

curl -X POST http://localhost:8000/memories/search 
 -H "Authorization: Bearer $ADMIN_API_KEY" 
 -H "Content-Type: application/json" 
 -d '{"query": "where do I deploy?", "user_id": "dev_01"}'

Second call returns your Hetzner sentence? Extraction, embedding, and retrieval are all working.

Common errors

“Vector dimension error: expected dim: 1536, got 768” – Set embedding_model_dims in vector_store.config to your embedder’s real output. Already created the collection at 1536? Drop it in Qdrant first – Mem0 won’t resize an existing collection.

“Collection memory_migrations already exists” – Community-reported collection creation conflict where Mem0 attempts to create the migrations collection on each startup without checking first. Restarting containers usually clears it; if not, delete the migrations collection manually via Qdrant’s REST API. (No official fix documented as of October 2025.)

401 Unauthorized on every call after upgrading – Self-hosted auth is on by default in v1.0. Upgrading from a pre-auth build? Set ADMIN_API_KEY, register an admin through the wizard, or set AUTH_DISABLED=true for local dev only. The error message doesn’t spell this out; the README does.

“Try Mem0 Platform” messages in your logs – Feature, not bug. v1.0 added contextual OSS-to-Platform notices that surface at first run and at scale/performance thresholds. Set MEM0_TELEMETRY=false in your compose file and they’re gone.

Upgrading and uninstall

SDK upgrade: pip install -U mem0ai. Server upgrade: git pull, then docker compose up -d --build. Postgres and Neo4j data survive on named Docker volumes – rebuilding the API image doesn’t touch them.

Check the migration guide before restarting after any server upgrade. Mem0 has shipped breaking schema changes in minor versions; rolling forward without reading the release notes has bitten users more than once.

Full uninstall:

# Stop containers, networks, AND named volumes (wipes all stored memories)
docker compose down -v

docker image rm mem0-selfhost:latest
cd .. && rm -rf mem0

Quick reality check: the compliance claims

The mem0.ai marketing page lists “SOC 2 (Type 1) and HIPAA compliant.” An independent review on OpenTechHub puts more detail on it: SOC 2 Type II is still in progress as of this writing, and HIPAA is self-attested rather than independently certified. Neither should be treated as a verified external audit.

Self-hosting sidesteps this entirely. Memories sit in databases you control, and there’s no call-home in the OSS build once you set MEM0_TELEMETRY=false. If regulated data is going in, self-host is the right call regardless of what the badges say.

FAQ

Do I need Neo4j, or can I skip the graph store?

Skip it. Graph memory only activates when you set graph_store in config with a Neo4j endpoint. Most use cases – chat personalization, preference recall – don’t need entity linking. Start without it.

How does self-hosted Mem0 compare to just using LangChain memory or Redis?

LangChain memory classes and Redis-backed session stores keep raw conversation history. On long sessions, that balloons your prompt tokens fast – you’re feeding the LLM a 50-turn transcript just to answer one question. Mem0 runs an LLM extraction pass on each message and stores facts instead of turns. Retrieval comes back as 4-5 sentences, not a conversation dump. Benchmark scores from the managed platform (as of October 2025): 92.5 on LoCoMo, 94.4 on LongMemEval, 64.1 on BEAM at 1M tokens – the README notes these reflect the hosted platform; open-source results should be directionally similar but expect some gap.

Is the open-source version actually free?

Yes – Apache-2.0, no call-home required once telemetry is off, no API key needed for self-hosted mode. The hosted Platform has a free tier, but the quota details weren’t clearly documented at time of writing. Check your dashboard for current limits rather than relying on the pricing page, which has changed without notice before.

Next step: run make bootstrap, wire your agent’s message handler to call client.add() once per turn and client.search() before the LLM call. Token usage should drop noticeably within a day of real traffic.