Data Retention Policy

The Data Retention Policy feature allows you to automatically clean up old messages and inactive channels from your application. This helps you manage storage costs, comply with data governance requirements, and keep your application focused on relevant, recent data.

Data retention cleanup permanently deletes data. Deleted messages, channels, and their associated data (reactions, attachments, members, etc.) cannot be recovered. Make sure you understand the implications before enabling retention policies.

Overview

Stream Chat supports two types of retention policies:

  • Old Messages (old-messages): Automatically deletes messages older than a specified age.
  • Inactive Channels (inactive-channels): Automatically deletes channels that have been inactive for longer than a specified period. A channel is considered inactive based on the most recent of its created_at, updated_at, or last_message_at timestamps.

Key characteristics:

  • Retention policies are configured at the app level using server-side API calls
  • Data is hard-deleted, not archived — deleted data cannot be recovered
  • Minimum retention age is 24 hours, maximum is 10 years (87,600 hours)
  • A 24-hour grace period applies after enabling or updating a policy before any cleanup begins
  • Cleanup runs asynchronously in the background — after enabling a policy, it may take hours or even days for all eligible data to be removed depending on the volume of data. During this period, expired data may still appear in API responses
  • Both policy types can be active simultaneously
  • When a policy is enabled or updated, email notifications are sent to all admin team members
  • Retention policy settings and cleanup run history are visible in the Stream Dashboard

The Retention Policy API is a server-side only feature. All endpoints require authentication with a server-side API key. Client-side tokens cannot access these endpoints.

Setting a Retention Policy

To enable automatic cleanup, create a retention policy by specifying the policy type and the maximum age in hours.

// Delete messages older than 6 months (4,380 hours)
const response = await client.post("/retention_policy", {
  policy: "old-messages",
  max_age_hours: 4380,
});

// Delete channels inactive for more than 6 months
const response = await client.post("/retention_policy", {
  policy: "inactive-channels",
  max_age_hours: 4380,
});

Request Parameters

FieldTypeDescriptionRequired
policystringThe policy type: old-messages or inactive-channelsYes
max_age_hoursintegerMaximum age in hours before data is eligible for deletion. Must be between 24 and 87,600 (10 years).Yes

If a policy already exists for the specified type, calling this endpoint again will update the existing policy with the new max_age_hours value.

Retrieving Retention Policies

Retrieve all active retention policies for your application.

const response = await client.get("/retention_policy");
console.log(response.retention_policies);
// [
//   { policy: "old-messages", config: { max_age_hours: 4380 }, enabled_at: "..." },
//   { policy: "inactive-channels", config: { max_age_hours: 8760 }, enabled_at: "..." }
// ]

Deleting a Retention Policy

Remove a retention policy to stop automatic cleanup for that policy type. Data that has already been deleted cannot be recovered.

// Stop deleting old messages
await client.post("/retention_policy/delete", {
  policy: "old-messages",
});

// Stop deleting inactive channels
await client.post("/retention_policy/delete", {
  policy: "inactive-channels",
});

Viewing Cleanup Run History

You can monitor the progress and history of retention cleanup runs. This is useful for verifying that cleanup is working as expected and understanding how much data has been removed.

// Get the latest cleanup runs
const response = await client.get("/retention_policy/runs", {
  limit: 10,
  offset: 0,
});

console.log(response.retention_policy_runs);
// [
//   {
//     policy: "old-messages",
//     date: "2026-03-20",
//     started_at: "2026-03-20T02:00:00Z",
//     finished_at: "2026-03-20T02:15:30Z",
//     status: "completed",
//     stats: { messages_deleted: 15420 }
//   }
// ]

Query Parameters

ParameterTypeDefaultDescription
limitinteger25Number of runs to return (max 100)
offsetinteger0Offset for pagination