# Tracker Stores in Rasa

Tracker stores are responsible for persisting conversation history and state in Rasa. Each conversation is represented as a tracker, which contains the sequence of events that have occurred during the conversation. Tracker stores enable your assistant to maintain context across multiple conversation sessions and retrieve historical conversation data.

Rasa provides several built-in tracker store implementations to suit different deployment scenarios and requirements:

- **InMemoryTrackerStore**: Stores conversations in memory (default). Suitable for development and testing.
- **SQLTrackerStore**: Uses SQL databases (PostgreSQL, SQLite, Oracle) for persistent storage.
- **RedisTrackerStore**: Leverages Redis for fast in-memory storage with optional persistence.
- **MongoTrackerStore**: Stores conversations in MongoDB, a document-oriented NoSQL database.
- **DynamoTrackerStore**: Uses AWS DynamoDB for cloud-based storage.

You can also implement a custom tracker store by extending the base `TrackerStore` class if you need to integrate with a different storage backend.

## User-Scoped Tracker Querying

New in 3.16

Rasa tracker stores now support user-scoped querying of conversations (referred to as trackers) and durable conversation metadata.

All tracker stores support user-scoped tracker querying and durable conversation-level properties such as `user_id` and `conversation_started_timestamp`. These properties enable efficient retrieval of all conversations for a specific user.

### Conversation Properties

Tracker stores persist the following fields in the tracker object:

- **`user_id`**: The unique identifier for the user associated with the conversation. This field is used for querying all conversations belonging to a specific user. Serialization of trackers omits `null user_id` values to optimize storage.
- **`conversation_started_timestamp`**: The timestamp when the conversation was first started. This field is used for ordering conversations chronologically.
- **`current_session_id`**: The session ID for the tracker's current session, derived from the metadata of the last stored event. This value is `null` when the last event is `ConversationInactive`, correctly reflecting that no active session exists.

The `conversation_started_timestamp` is automatically backfilled on save/update for backward compatibility with existing trackers that may not have this field.

Each tracker store implementation provides optimized mechanisms for user-scoped retrieval, ordering, and pagination as described in their respective sections below.

## InMemoryTrackerStore (default)

`InMemoryTrackerStore` is the default tracker store. It is used if no other tracker store is configured. It stores the conversation history in memory.

### Configuration

No configuration is needed to use the `InMemoryTrackerStore`.

### User-Scoped Querying

The `InMemoryTrackerStore` implements user-scoped tracker querying by scanning all stored tracker keys and retrieving each tracker to filter by `user_id`.

#### Implementation Details

- **Full Scan**: The implementation scans all stored tracker keys in memory and retrieves each tracker to filter by `user_id`. This approach is feasible for in-memory storage due to the typically smaller dataset size.
- **Ordering and Pagination**: After filtering, the trackers are ordered by `conversation_started_timestamp` and `sender_id`, and paginated in memory using standard Python sorting and slicing techniques.

## SQLTrackerStore

You can use an `SQLTrackerStore` to store your assistant's conversation history in an SQL database.

### Configuration

To set up Rasa with SQL the following steps are required:

1. Add required configuration to your `endpoints.yml`:

```yaml
tracker_store:
    type: SQL
    dialect: "postgresql"  # the dialect used to interact with the db
    url: ""  # (optional) host of the sql db, e.g. "localhost"
    db: "rasa"  # path to your db
    username:  # username used for authentication
    password:  # password used for authentication
    query: # optional dictionary to be added as a query string to the connection URL
      driver: my-driver
```

2. To start the Rasa server using your SQL backend, add the `--endpoints` flag, e.g.:

```bash
rasa run -m models --endpoints endpoints.yml
```

#### Configuration Parameters

- `domain` (default: `None`): Domain object associated with this tracker store
- `dialect` (default: `sqlite`): The dialect used to communicate with your SQL backend. Consult the [SQLAlchemy docs](https://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls) for available dialects.
- `url` (default: `None`): URL of your SQL server
- `port` (default: `None`): Port of your SQL server
- `db` (default: `rasa.db`): The path to the database to be used
- `username` (default: `None`): The username which is used for authentication
- `password` (default: `None`): The password which is used for authentication
- `event_broker` (default: `None`): Event broker to publish events to
- `login_db` (default: `None`): Alternative database name to which initially connect, and create the database specified by `db` (PostgreSQL only)
- `query` (default: `None`): Dictionary of options to be passed to the dialect and/or the DBAPI upon connect

### Compatible Databases

The following databases are officially compatible with the `SQLTrackerStore`:

- PostgreSQL
- Oracle > 11.0
- SQLite

### Configuring Oracle

To use the SQLTrackerStore with Oracle, there are a few additional steps. First, create a database `tracker` in your Oracle database and create a user with access to it.  Create a sequence in the database with the following command:

```sql
CREATE SEQUENCE username.events_seq;
```

Next you have to extend the Rasa image to include the necessary drivers and clients. First download the [Oracle Instant Client](https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html), rename it to `oracle.rpm` and store it in the directory from where you'll be building the docker image. Copy the following into a file called `Dockerfile`:

```bash
FROM rasa/rasa:latest-full

# Switch to root user to install packages
USER root

RUN apt-get update -qq && apt-get install -y --no-install-recommends alien libaio1 && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Copy in oracle instaclient
COPY oracle.rpm oracle.rpm

# Install the Python wrapper library for the Oracle drivers
RUN pip install cx-Oracle

# Install Oracle client libraries
RUN alien -i oracle.rpm

USER 1001
```

Then build the docker image:

```bash
docker build . -t rasa-oracle:latest-oracle-full
```

### User-Scoped Querying

The `SQLTrackerStore` implements user-scoped tracker querying through a dedicated `users` table that maps `sender_id` to `user_id` along with the timestamp when the conversation was started.

### Implementation Details

- **Users Table**: A separate `users` table is created with columns for `sender_id` (mapped to `user_id`) and `conversation_started_timestamp`.
- **Bulk Retrieval**: User-scoped queries use two bulk operations: a paginated `users` table query to retrieve `sender_id`s for the given `user_id`, followed by a single `events WHERE sender_id IN (...)` fetch to load all events for those conversations. This ensures query count stays constant regardless of conversation volume.
- **Database-Level Ordering and Pagination**: The `sender_id`s are ordered by `conversation_started_timestamp` and paginated using SQL `LIMIT`/`OFFSET` clauses for optimal performance.

## RedisTrackerStore

You can store your assistant's conversation history in Redis by using the `RedisTrackerStore`. Redis is a fast in-memory key-value store which can optionally also persist data.

### High Availability Support

New in 3.14

Redis high availability support is now available for the `RedisTrackerStore`. You can now deploy with Redis Cluster for horizontal scaling or Redis Sentinel for automatic failover.

The `RedisTrackerStore` now supports Redis high availability deployments through Redis Cluster and Redis Sentinel modes, enabling enterprise-grade scalability and reliability for production deployments.

### Configuration

To set up Rasa with Redis the following steps are required:

1. Add required configuration to your `endpoints.yml`:

```yaml
tracker_store:
    type: redis
    url: <url of the redis instance, e.g. localhost>
    port: <port of your redis instance, usually 6379>
    key_prefix: <alphanumeric value to prepend to tracker store keys>
    db: <number of your database within redis, e.g. 0. Not used in cluster mode>
    password: <password used for authentication>
    use_ssl: <whether or not the communication is encrypted, default `false`>
    deployment_mode: <standard, cluster, or sentinel>
    endpoints: <list of redis cluster/sentinel node addresses in the format host:port, only used in cluster or sentinel mode>
    sentinel_service: <name of the redis sentinel service, only used in sentinel mode>
```

2. To start the Rasa server using your SQL backend, add the `--endpoints` flag, e.g.:

```bash
rasa run -m models --endpoints endpoints.yml
```

### Using IAM to authenticate to AWS ElastiCache for Redis

New in 3.14

You can use IAM authentication to connect to AWS ElastiCache for Redis without needing to provide static credentials.

If your Rasa instance is running on an AWS service that supports IAM roles (e.g. EC2), you can use IAM authentication to connect to AWS ElastiCache for Redis without needing to provide static credentials. To do so, you need to ensure that your AWS ElastiCache cluster is configured to allow IAM authentication by creating an AWS ElastiCache user with IAM authentication mode enabled.

You also need to set up your Rasa instance with an appropriate IAM role that has the permissions to access the AWS ElastiCache cluster or replication group:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "elasticache:Connect"
            ],
            "Resource": "*"
        }
    ]
}
```

### User-Scoped Querying

The `RedisTrackerStore` implements user-scoped tracker querying through a secondary index that enables O(1) lookup of all conversations for a specific user.

## MongoTrackerStore

You can store your assistant's conversation history in [MongoDB](https://www.mongodb.com/) using the `MongoTrackerStore`. MongoDB is a free and open-source cross-platform document-oriented NoSQL database.

### Configuration

1. Add required configuration to your `endpoints.yml`:

```yaml
tracker_store:
    type: mongod
    url: <url to your mongo instance, e.g. mongodb://localhost:27017>
    db: <name of the db within your mongo instance, e.g. rasa>
    username: <username used for authentication>
    password: <password used for authentication>
    auth_source: <database name associated with the user's credentials>
```

2. To start the Rasa server using your configured MongoDB instance,
add the `--endpoints` flag, for example:

```bash
rasa run -m models --endpoints endpoints.yml
```

### User-Scoped Querying

The `MongoTrackerStore` implements user-scoped querying through MongoDB indices and aggregation pipelines for efficient querying and ordering.

## DynamoTrackerStore

You can store your assistant's conversation history in [DynamoDB](https://aws.amazon.com/dynamodb/) by using a `DynamoTrackerStore`. DynamoDB is a hosted NoSQL database offered by Amazon Web Services (AWS).

### Configuration

1. Add required configuration to your `endpoints.yml`:

```yaml
tracker_store:
    type: dynamo
    table_name: <name of the table to create, e.g. rasa>
    region: <name of the region associated with the client>
```

## Custom Tracker Store

If you need a tracker store which is not available out of the box, you can implement your own. This is done by extending the base class `TrackerStore` and one of the provided mixin classes that implement the `serialise_tracker` method: `SerializedTrackerAsText` or `SerializedTrackerAsDict`.
