How Does Mem0 Store Memories and What Database Backend Options Are Available

Mem0 stores memories as dense vector embeddings with metadata in a configurable vector store while maintaining an immutable audit log in SQLite, supporting over 20 database backends including Qdrant, Chroma, PostgreSQL/pgvector, Pinecone, and cloud-native options from Azure, AWS, and Google Cloud.

Mem0 (pronounced "mem-zero") is an open-source memory layer for AI applications that persists contextual information across conversations. Understanding how Mem0 stores memories and what database backend options are available helps architects select the right persistence strategy for production LLM systems. The platform implements a dual-layer storage architecture that separates fast vector retrieval from historical change tracking.

How Mem0 Stores Memories: The Dual-Layer Architecture

Mem0 organizes persistence into two distinct storage layers, each serving a specific purpose in the memory lifecycle.

Vector Store Layer

The vector store holds dense embedding vectors generated by an embedder model alongside rich metadata payloads. When you call Memory.add in mem0/memory/main.py, the system converts text into a vector using self.embedding_model.embed, then persists both the vector and metadata (including user_id, agent_id, run_id, timestamps, and content hashes) to the configured backend. Retrieval operations like Memory.search and Memory.get_all query this layer using vector similarity combined with metadata filters, translating user queries into backend-native filter objects via _create_filter methods implemented in each provider.

History Database Layer

The history database is a lightweight SQLite instance managed by SQLiteManager in mem0/memory/storage.py. This layer tracks immutable change events—add, update, and delete operations—for every memory. Unlike the vector store, this component is not configurable; it always uses SQLite to ensure local auditability. When self.db.add_history is invoked during memory creation, it logs the operation type, timestamp, and payload diff, enabling full revision history inspection via the memory.history() method.

The Memory Persistence Pipeline

The Memory.add method in mem0/memory/main.py orchestrates a five-step persistence workflow:

  1. Embed the input text using self.embedding_model.embed to generate a dense vector representation.
  2. Generate a UUID to uniquely identify the memory.
  3. Assemble a payload containing the raw text, content hash, creation timestamp, and session identifiers (user_id, agent_id, etc.).
  4. Insert the vector and payload into the chosen vector store via self.vector_store.insert.
  5. Log the ADD event to the SQLite history table via self.db.add_history for audit purposes.

Retrieval follows the reverse path: Memory.search embeds the query string, queries the vector store with optional metadata filters, and normalizes returned payloads into MemoryItem objects.

Available Database Backend Options

Mem0 supports 20+ vector store providers enumerated in mem0/vector_stores/configs.py through the _provider_configs mapping. Each provider implements the VectorStoreBase interface defined in mem0/vector_stores/base.py.

High-Performance and Cloud-Native Options

PostgreSQL and Relational Extensions

Cloud Provider Integrations

Local and Embedded Options

NoSQL and Specialized Stores

Integration Wrappers

Configuring and Using Mem0 Storage

Initializing with a Specific Backend

Configure your chosen provider via MemoryConfig in mem0/configs/base.py:

from mem0 import Memory
from mem0.configs.base import MemoryConfig

config = MemoryConfig(
    vector_store={
        "provider": "qdrant",
        "config": {
            "host": "localhost",
            "port": 6333,
            "collection_name": "mem0"
        }
    },
    embedder={
        "provider": "openai",
        "config": {"model": "text-embedding-3-small"}
    },
    llm={
        "provider": "openai",
        "config": {"model": "gpt-4", "api_key": "YOUR_KEY"}
    }
)

memory = Memory(config)

Adding Memories with Metadata

The add method stores vectors and logs history automatically:

result = memory.add(
    "User prefers Python for data science tasks.",
    user_id="alice",
    metadata={"source": "onboarding", "department": "engineering"}
)

# Creates UUID, embeds text, inserts to vector store, logs to SQLite history

Retrieving with Metadata Filters

Filter queries translate to backend-specific syntax (e.g., Qdrant Filter objects or MongoDB queries):

memories = memory.search(
    "What programming languages does Alice prefer?",
    user_id="alice",
    filters={"department": "engineering"}
)

Accessing the Immutable History

Query the SQLite audit log independently of the vector store:

history = memory.history(memory_id="uuid-from-result")

# Returns list of change events from SQLiteManager

Summary

  • Mem0 implements a dual-layer storage architecture separating vector persistence from audit logging.
  • The vector store layer is configurable via VectorStoreConfig in mem0/configs/base.py, supporting 20+ backends including Qdrant, pgvector, Pinecone, and cloud providers.
  • The history layer always uses SQLite via SQLiteManager in mem0/memory/storage.py to track immutable change events.
  • The Memory.add pipeline in mem0/memory/main.py orchestrates embedding, UUID generation, payload assembly, vector insertion, and history logging.
  • Metadata filtering is normalized across backends through provider-specific _create_filter implementations while maintaining consistent API semantics.

Frequently Asked Questions

What is the difference between the vector store and history database in Mem0?

The vector store persists dense embeddings and searchable metadata using configurable backends like Qdrant or Chroma, enabling semantic similarity search. The history database is a fixed SQLite instance that records immutable change events (additions, updates, deletions) for audit trails, implemented in mem0/memory/storage.py via SQLiteManager.

Which database backend should I choose for Mem0?

Select Qdrant or Weaviate for high-throughput production environments, pgvector or Supabase if your infrastructure already relies on PostgreSQL, Chroma or FAISS for local development and testing, and Pinecone or Azure AI Search for fully managed cloud deployments requiring minimal operational overhead.

How does Mem0 handle metadata filtering across different vector stores?

Mem0 normalizes metadata filters through the _create_filter method implemented in each provider file (e.g., mem0/vector_stores/qdrant.py). When you call memory.search() with filters, the system translates standard Python dictionaries into backend-native query formats—such as Qdrant Filter objects or MongoDB query documents—ensuring consistent behavior across all 20+ supported databases.

Can I migrate Mem0 memories between different database backends?

Mem0 does not provide an automatic migration tool, but you can export memories using memory.get_all() and re-import them into a new Memory instance configured with a different vector_store provider. Note that the SQLite history database is instance-specific and does not migrate between backends, as it serves local audit logging rather than application state.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →