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

# Message Storage

Ably stores all messages for two minutes by default. This can be increased up to a year, or longer, depending on your account package. It is also possible to persist the last message sent to a channel for a year. Ably [integrations](/docs/platform/integrations) can also be used to send messages outside of Ably for long-term storage.

## Default storage (2 minutes)

The default message storage of two minutes enables clients that briefly disconnect from Ably to [automatically retrieve](/docs/connect/states) any messages they may have missed. These messages can also be retrieved using the [history](/docs/pubsub/history) feature, and this applies to both regular messages and [presence messages](/docs/pubsub/presence).

<Code>
  ```javascript theme={null}
  // Messages are automatically stored for 2 minutes
  await channel.publish('event', 'data');

  // Retrieve recent messages
  const history = await channel.history();
  console.log(`Retrieved ${history.items.length} messages`);
  ```
</Code>

## Persist all messages

If you need to retain messages for longer than the default two minutes you can enable persisted history by setting a [channel rule](/docs/channels#rules).

The time that messages will be stored for depends on your account package:

| Package        | Minimum  | Maximum  |
| -------------- | -------- | -------- |
| **Free**       | 24 hours | 24 hours |
| **PAYG**       | 72 hours | 365 days |
| **Enterprise** | 72 hours | Custom   |

<Aside data-type="note">
  Every message that is persisted to, or retrieved from, disk counts as an extra message towards your monthly quota. For example, with persistence enabled a published message counts as two messages for your monthly quota.
</Aside>

### Enable persisted storage

To enable persisted storage for a channel:

<Steps>
  1. Sign in to your Ably account
  2. Select your app
  3. Go to the **Settings** tab
  4. Click **Add new rule** under Channel Rules
  5. Enter the channel name or namespace
  6. Check **Persist all messages**
  7. Configure the retention period
  8. Click **Create channel rule**
</Steps>

### Query persisted messages

<Code>
  ```javascript theme={null}
  // Get messages from the last 24 hours
  const oneDayAgo = Date.now() - (24 * 60 * 60 * 1000);

  const history = await channel.history({
    start: oneDayAgo,
    limit: 100
  });

  console.log(`Retrieved ${history.items.length} persisted messages`);
  ```
</Code>

## Persist last message only

You can persist just the last message sent to a channel for one year by setting a [channel rule](/docs/channels#rules). This is useful for state channels where you only need the most recent value.

### Enable last message persistence

<Steps>
  1. Sign in to your Ably account
  2. Select your app
  3. Go to the **Settings** tab
  4. Click **Add new rule** under Channel Rules
  5. Enter the channel name or namespace
  6. Check **Persist last message**
  7. Click **Create channel rule**
</Steps>

### Retrieve the last message

Use the [rewind channel option](/docs/channels/options/rewind) to get the last persisted message:

<Code>
  ```javascript theme={null}
  // Get the last message when attaching
  const channel = realtime.channels.get('status-updates', {
    params: { rewind: '1' }
  });

  await channel.subscribe((message) => {
    // First message received will be the last persisted message
    console.log('Last state:', message.data);
  });
  ```
</Code>

Or retrieve it via the history API:

<Code>
  ```javascript theme={null}
  const history = await channel.history({ limit: 1 });
  if (history.items.length > 0) {
    console.log('Last message:', history.items[0].data);
  }
  ```
</Code>

## Storage costs

Understand the message costs for storage:

| Operation                      | Message Count                              |
| ------------------------------ | ------------------------------------------ |
| **Publish**                    | 1 message                                  |
| **Publish (with persistence)** | 2 messages (1 for publish + 1 for storage) |
| **Retrieve from history**      | 1 message per retrieved message            |
| **Last message persistence**   | 1 additional message when published        |

<Aside data-type="note">
  Messages are counted in 5 KiB chunks. A 15 KiB message counts as 3 messages.
</Aside>

## Store messages outside Ably

For long-term storage, complex queries, or compliance requirements, use [integrations](/docs/platform/integrations) to send messages to your own systems:

### Webhooks

Send messages to your server via HTTP webhooks:

<Steps>
  1. Go to the **Integrations** tab in your dashboard
  2. Click **New Integration Rule**
  3. Select **Webhook**
  4. Configure your endpoint URL
  5. Select the channels to integrate
  6. Click **Create**
</Steps>

### Message queues

Stream messages to message queues:

* **AWS Kinesis**: For real-time data streaming
* **AWS SQS**: For reliable message queuing
* **Azure Event Hubs**: For event streaming
* **Google Cloud Pub/Sub**: For asynchronous messaging

### Databases

Use serverless functions to store in your database:

<Code>
  ```javascript theme={null}
  // Example: AWS Lambda function triggered by Ably webhook
  exports.handler = async (event) => {
    const message = JSON.parse(event.body);
    
    // Store in DynamoDB
    await dynamodb.putItem({
      TableName: 'Messages',
      Item: {
        id: message.id,
        channel: message.channel,
        data: message.data,
        timestamp: message.timestamp
      }
    });
    
    return { statusCode: 200 };
  };
  ```
</Code>

## Message deletion

Ably does not currently provide an API to delete persisted messages from history. Once messages are stored with persisted history enabled, they remain for the entire configured storage period.

If you need to delete specific messages from history, [contact support](https://ably.com/support).

## Best practices

### Choose the right storage option

<Code>
  ```javascript theme={null}
  // State channels - use last message persistence
  const statusChannel = realtime.channels.get('user-status');

  // Event streams - use full persistence if needed
  const eventsChannel = realtime.channels.get('analytics-events');

  // Real-time only - use default 2-minute storage
  const chatChannel = realtime.channels.get('live-chat');
  ```
</Code>

### Use channel namespaces for storage rules

Apply storage rules to channel namespaces instead of individual channels:

* `persisted:*` - All channels with full persistence
* `state:*` - All channels with last message persistence
* `live:*` - All channels with default 2-minute storage

### Monitor storage costs

Track your message usage in the dashboard to understand storage costs:

1. Go to your app in the dashboard
2. Click the **Usage** tab
3. View message counts by type
4. Monitor persisted vs. ephemeral messages

## Next steps

* Learn about [message history](/docs/pubsub/history)
* Set up [integrations](/docs/platform/integrations) for external storage
* Configure [channel rules](/docs/channels#rules)
* Understand [pricing](/docs/platform/pricing)
