# Data Retention

Data retention policies automatically delete old activities from your app. Use them to manage storage, meet data governance requirements, and keep feeds focused on recent content.

>
> **Warning:** Retention deletes activities, together with their comments, reactions, and bookmarks. Deleted activities are backed up for **60 days** and can be restored by [contacting support](https://getstream.io/contact/support/). After that, they cannot be recovered.
>

## Overview

- If you set no policy, activities are kept forever. Nothing ages out on its own.
- A policy deletes activities older than the age you choose, measured from the activity's `created_at`.
- A policy covers all activities in the app, or only activities posted to the feed groups you list. An app can have up to 20 policies.
- Policies are managed with server-side API calls, or under **Feeds > Settings > Retention policy** for your app in the [Stream Dashboard](https://getstream.io/signin/?product=feeds).
- The minimum age is **24 hours** and the maximum is **5 years** (43,800 hours). [Contact support](https://getstream.io/contact/support/) if your compliance requirements need a longer window.
- A **24-hour grace period** applies after you set or update a policy before anything is deleted, so a mistaken change can be reverted.
- Cleanup runs in the background. Depending on how much data is eligible, it can take hours or days to remove everything, and expired activities may still appear in API responses until then.
- When a policy is set or updated (unless retention is paused), an email is sent to your organization's admins.

## Policies

Each policy has a name you choose (`policy`), up to 64 letters, numbers, dashes, or underscores.

- **`old-activities`** is the app-wide policy. It always covers every feed group.
- **Any other name** creates a policy limited to the feed groups you list in `feed_groups`. Pass an empty list to cover all feed groups.

For example, to keep stories for 30 days and everything else for a year, set `old-activities` to one year and a policy named `stories` to 30 days, scoped to the `stories` feed group. An activity is deleted as soon as any policy that covers it says it is old enough.

>
> **Info:** A scoped policy matches the feeds an activity was **posted to** (the feeds in its `feeds` list), not the timelines it reaches through follows. Scope a policy to the feed groups your activities are actually posted into, such as `user` or `stories`. A policy scoped to a group that only receives activities through follows, such as `timeline`, matches nothing.
>

## What gets deleted

When an activity is deleted by retention:

- Its comments, reactions (on the activity and on its comments), bookmarks, and pins are deleted with it.
- It is removed from every feed it was posted to and from followers' timelines.
- Activities that share it (activities with it as their `parent_id`) are **not** deleted. They have their own age and are deleted once they pass it, and until then they are returned without the shared activity.
- Activities that were already soft-deleted are skipped.

## Setting a retention policy

Setting a policy creates it, or updates it if a policy with that name already exists. Updating a policy restarts its 24-hour grace period.

```csharp label="C#"
// Delete all activities older than one year (8,760 hours)
await _feedsV3Client.FeedsSetRetentionPolicyAsync(
    new SetFeedsRetentionPolicyRequest
    {
        Policy = "old-activities",
        MaxAgeHours = 8760,
    });
```

To limit a policy to some feed groups, give it a name of your own and list the groups in `feed_groups`:

```js label="Node.js"
// Delete activities posted to stories feeds after 30 days (720 hours)
await client.feeds.feedsSetRetentionPolicy({
  policy: "stories",
  max_age_hours: 720,
  feed_groups: ["stories"],
});
```

### Request parameters

| Field           | Type     | Description                                                                                                                                       | Required                     |
| --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| `policy`        | string   | The policy name. `old-activities` is the app-wide policy; any other name is a policy of your own.                                                 | Yes                          |
| `max_age_hours` | integer  | Age in hours after which an activity is deleted. Between 24 and 43,800 (5 years).                                                                 | Yes                          |
| `feed_groups`   | string[] | The feed groups the policy covers, up to 20. Each must exist in your app. An empty list covers all feed groups. Not allowed for `old-activities`. | For a new policy of your own |
| `enabled`       | boolean  | `false` saves the policy without deleting anything. See [Pausing retention](#pausing-retention). Defaults to `true`.                              | No                           |

## Pausing retention

Retention can be paused for the whole app without deleting your policies. Pass `enabled: false` when you set a policy:

```csharp label="C#"
await _feedsV3Client.FeedsSetRetentionPolicyAsync(
    new SetFeedsRetentionPolicyRequest
    {
        Policy = "old-activities",
        MaxAgeHours = 8760,
        Enabled = false,
    });
```

>
> **Warning:** Pausing and resuming apply to **every** policy in the app. Setting any policy without `enabled: false` resumes retention for all of them, and each one starts a new 24-hour grace period.
>

## Retrieving retention policies

The response lists the app's policies and whether retention is enabled.

```csharp label="C#"
var response = await _feedsV3Client.FeedsGetRetentionPolicyAsync();
```

## Deleting a retention policy

Deleting a policy stops it, but does not bring back activities it already deleted. To restore those, contact support within the 60-day backup window. Deleting the last policy turns retention off for the app.

```csharp label="C#"
await _feedsV3Client.FeedsDeleteRetentionPolicyAsync(
    new DeleteFeedsRetentionPolicyRequest { Policy = "stories" });
```

## Viewing cleanup run history

Each cleanup run reports how many activities it deleted, per policy and day. Use it to confirm that cleanup is working through your data. Runs reporting deletions mean cleanup is progressing. [Contact support](https://getstream.io/contact/support/) if the backlog stays flat across several days.

```csharp label="C#"
var response = await _feedsV3Client.FeedsGetRetentionPolicyRunsAsync(
    new GetFeedsRetentionPolicyRunsRequest
    {
        FilterConditions = new Dictionary<string, object>
        {
            { "policy", new Dictionary<string, object> { { "$eq", "stories" } } }
        },
        Sort = new List<SortParamRequest>
        {
            new SortParamRequest { Field = "date", Direction = -1 }
        },
        Limit = 10,
    });
```

| Parameter           | Type    | Description                                                                                         |
| ------------------- | ------- | --------------------------------------------------------------------------------------------------- |
| `filter_conditions` | object  | Filter by `policy` and/or `date` (for example `{"date": {"$gte": "2026-01-01"}}`)                   |
| `sort`              | array   | Sort by `policy` or `date`. Each entry has `field` and `direction` (`-1` descending, `1` ascending) |
| `limit`             | integer | Number of runs per page                                                                             |
| `next`              | string  | Cursor for the next page, from the previous response                                                |
| `prev`              | string  | Cursor for the previous page, from the previous response                                            |

Run history is kept for **6 months**. Export it periodically if you need a longer record.

## Deletion and backups

Before each cleanup run deletes a batch, Stream backs up the activities and the data deleted with them. These backups are kept for **60 days**, and support can restore from them within that window. After 60 days they are deleted and the data cannot be recovered.

Stream's operational backups for disaster recovery are separate and expire on their own schedule. [Contact support](https://getstream.io/contact/support/) if you have a regulatory requirement that depends on the exact backup window.

---

For the most recent version of this documentation, visit [https://getstream.io/activity-feeds/docs/dotnet-csharp/data-retention/](https://getstream.io/activity-feeds/docs/dotnet-csharp/data-retention/).