> ## Documentation Index
> Fetch the complete documentation index at: https://docs.openmem.blog/llms.txt
> Use this file to discover all available pages before exploring further.

# Switch memory providers without changing app code

> OMP separates provider choice from application logic. Change a single constructor argument to move between Postgres, Mem0, Supermemory, and Letta.

Every OMP method — `add`, `search`, `context`, and the rest — works identically no matter which backend you choose. Your application code calls the same functions with the same arguments; only the `Memory(...)` constructor line changes when you want a different provider. This means you can prototype with Postgres, deploy with Mem0, and let each user pick their own backend, all without modifying the logic that reads and writes memories.

## Swap the constructor, keep the code

The examples below all use the same `add` and `search` calls. The only difference is the first line.

```python theme={null}
import os
from openmem import Memory

# Start with Postgres
mem = Memory(provider="postgres", url=os.environ["PG_URL"])

# Switch to Mem0 — application code below is unchanged
mem = Memory(provider="mem0", api_key=os.environ["MEM0_API_KEY"])

# Switch to Supermemory
mem = Memory(provider="supermemory", api_key=os.environ["SUPERMEMORY_API_KEY"])

# Switch to Letta
mem = Memory(provider="letta", api_key=os.environ["LETTA_API_KEY"])

# Same calls work with every provider
mem.add(content="user prefers dark mode", user_id="kek", scope="ui/preferences")
results = mem.search("dark mode", user_id="kek")
```

## Let users choose their own backend

You can read the provider name and configuration from user settings and forward them directly to the constructor. Your application never needs a conditional branch per provider.

```python theme={null}
provider = user_settings.get("memory_backend")
mem = Memory(provider=provider, **user_settings.get("memory_config"))
```

This pattern is how multi-tenant apps can give each user sovereignty over their own memory storage.

## Install extras

The core `openmem` package includes the Postgres adapter. Each third-party provider requires its own extras group:

<Steps>
  <Step title="Postgres (included by default)">
    ```bash theme={null}
    pip install openmem
    ```
  </Step>

  <Step title="Mem0">
    ```bash theme={null}
    pip install 'openmem[mem0]'
    ```
  </Step>

  <Step title="Supermemory">
    ```bash theme={null}
    pip install 'openmem[supermemory]'
    ```
  </Step>

  <Step title="Letta">
    ```bash theme={null}
    pip install 'openmem[letta]'
    ```
  </Step>
</Steps>

## Store provider config in environment variables

<Tip>
  Keep credentials out of your source code. Store the provider name and any API keys or URLs as environment variables, then read them at startup. This also makes it trivial to change providers per deployment environment without touching application code.
</Tip>

```python theme={null}
import os
from openmem import Memory

# All config comes from the environment
mem = Memory(
    provider=os.environ["OMP_PROVIDER"],
    api_key=os.environ.get("OMP_API_KEY"),
    url=os.environ.get("OMP_URL"),
)
```

## Asynchronous ingestion on hosted providers

<Note>
  Mem0 and Supermemory may return `status="queued"` on `add()`. The memory is accepted but ingested asynchronously on the provider's infrastructure. Check the `status` field on the returned `MemoryRecord` before assuming the record is immediately searchable.

  ```python theme={null}
  record = mem.add(content="user prefers dark mode", user_id="kek")
  if record.status == "queued":
      # Ingestion is in progress; the record will become searchable shortly
      pass
  ```

  Postgres always returns `status="done"` — writes are synchronous and the record is immediately searchable.
</Note>
