# Configure zero-retention mode

Last validated Jul 2, 2026

\[Missing snippet: aperture\_release\_note.mdx]

\[Missing snippet: aperture\_terms.mdx]

By default, Aperture captures request and response bodies so you can browse them in the dashboard. The [retention settings][kb-aperture-retention] let you shorten or eliminate how long that content is kept. This guide shows you how to configure an instance for zero data retention, where prompt and response content is never written to disk, for example to minimize data stored at rest or to meet a strict internal or contractual data-handling requirement.

You configure zero data retention entirely through the Aperture configuration, with no code changes required.

## Prerequisites

Before you begin, ensure you have the following:

* An [Aperture instance][kb-aperture-get-started] with at least one provider configured.
* Admin access to the [Aperture configuration][kb-aperture-configuration], including either the **Database** settings page or the raw configuration editor.

The configuration is written in HUJSON, which is JSON that also permits comments and trailing commas. Standard JSON is valid HUJSON.

## How retention works

Aperture stores captured content in its database and runs a background purge worker that deletes content once it passes the configured retention window. You control this through the top-level `database` object, specifically its [`retention`][kb-aperture-retention] block:

* `duration` sets the retention window. The special value `"0"` enables zero data retention. For non-zero values, the minimum is one hour and the maximum is 3650 days (10 years).
* `purge` lists which categories of data the purge removes.
* `require_export` optionally gates deletion on a successful S3 export.

These settings govern two categories of data. *Captured content* is the recorded request and response bodies, headers, and raw data. *Tool data* is tool names, parameters, and counts. The settings do not affect usage metrics such as token counts, estimated cost, model, and identity, which Aperture records separately.

With `duration: "0"` and `require_export: false`, Aperture applies write-time redaction: request and response bodies, headers, and raw bodies are never written to disk, and tool data is also dropped when you list `"tools"` under `purge`. Aperture still inserts a capture row, but marks it purged at write time so it carries only metadata. With `require_export: true`, content is written, exported to S3, and then purged locally, which keeps an off-box archive while keeping the instance itself clean.

## Step 1: Choose a retention posture

The three fields combine into meaningfully different behaviors. Choose the row that matches your requirement:

| Goal                                 | `duration` | `purge`                 | `require_export` |
| ------------------------------------ | ---------- | ----------------------- | ---------------- |
| Storage management only              | `"30d"`    | `["captures"]`          | `false`          |
| Storage management, strict           | `"30d"`    | `["captures", "tools"]` | `false`          |
| Never store anything on disk         | `"0"`      | `["captures", "tools"]` | `false`          |
| Archive to S3, then scrub locally    | `"0"`      | `["captures"]`          | `true`           |
| Keep a 90-day debug window, archived | `"90d"`    | `["captures"]`          | `true`           |

For a true never-store requirement, choose **Never store anything on disk**. Combining `duration: "0"` with `purge: ["captures", "tools"]` is the strictest posture: no prompt-derived content is ever stored.

If you must retain an off-box copy for long-term archiving, choose **Archive to S3, then scrub locally** and confirm that [S3 export][kb-aperture-export-s3] is already configured. The `require_export` gate only purges content once an export succeeds.

## Step 2: Back up the current configuration

\[Missing snippet: aperture\_admin\_nav.mdx] Copy the current configuration to a local file before you change anything, so you can revert if needed.

The **Database** settings page presents the retention duration, purge categories, and export gating as form controls and shows a live preview of how many stored captures a given duration would affect. Alternatively, edit the `database` block directly in the configuration editor. This guide shows the underlying configuration so the result is unambiguous.

## Step 3: Set the never-store configuration

Set the `database` block so its `retention` matches your chosen posture. For the never-store-anything posture, use the following:

```json
"database": {
  "save_raws": false,
  "retention": {
    "duration": "0",
    "purge": ["captures", "tools"],
    "require_export": false
  }
}
```

Leave `save_raws` set to `false`. Raw body capture is a debugging aid that stores even more content, so it works against a never-store goal. Do not set `keep_encrypted_blobs` to `true` either, because that preserves encrypted request and response content without redaction, which also runs counter to zero data retention.

If you chose the archive-to-S3 posture instead, set `duration` to `"0"`, leave `purge` at `["captures"]`, and set `require_export` to `true`. That path depends on a working [S3 export][kb-aperture-export-s3] configuration. Verify it exports successfully before relying on it to gate purging.

## Step 4: Preview the impact before saving

A switch to `duration: "0"` sets the purge cutoff to the current moment, which makes every currently stored capture that has not yet been purged eligible for deletion on the next purge cycle. Confirm how much existing content the change removes before you commit it.

On the **Database** settings page, the retention section shows an impact preview for the duration you are about to set: the number of captures currently older than that duration. For `"0"`, this covers every stored capture that has not yet been purged.

To also retrieve the timestamp of the oldest affected capture, call the admin preview endpoint that backs that UI directly:

```shell
curl "https://<aperture-hostname>/api/retention/impact?duration=0" \
  -H "content-type: application/json"
```

The response reports `affected_count` and, when present, `oldest_capture`. This endpoint is admin-only and is not part of the public API surface.

## Step 5: Save and verify

Saving applies the change immediately. Until you save, the instance keeps storing content under the old policy.

1. Save the configuration. If you used the raw editor, the save should succeed without a validation error. A common mistake is a missing comma in the `database` block.
2. Send a normal request through the instance.
3. In the dashboard's [logs or session view][kb-aperture-dashboard], locate the request you sent. The usage metrics (model, token counts, and estimated cost) should appear, but the request and response bodies should be empty or redacted rather than showing the prompt text.

The presence of metrics with absent content is the expected result: Aperture still meters the request, but never stores what was in it.

## Troubleshooting

### Content is still visible in the dashboard

First, confirm the configuration saved. Reopen the configuration editor or the **Database** settings page and check that `retention.duration` reads `"0"` and `purge` lists the categories you intended.

Previously stored content is removed by the background purge worker, not instantly at save time. The impact preview tells you what is queued for deletion; the actual removal happens on the next purge cycle. New requests after the save store nothing, so test with a fresh request rather than an old one when verifying never-store behavior.

### Tool parameters still appear though bodies are gone

This means `purge` is set to `["captures"]` only. Tool names, parameters, and counts are a separate category. Add `"tools"` to the `purge` list to remove them.

### Captures are not being purged in archive-to-S3 mode

When `require_export` is `true`, content is purged only after it has been successfully exported to S3. If exports are failing or S3 is not configured, Aperture intentionally keeps content past its retention window rather than deleting data that was never archived. Verify the [S3 export][kb-aperture-export-s3] is configured and succeeding.

## Security considerations

Zero data retention protects against at-rest exposure of prompt and response content. With `duration: "0"` and no export gating, that content is never written to the instance's disk, so a later compromise of the instance or its database cannot reveal prompts that already passed through. Setting `purge` to `["captures", "tools"]` extends that protection to tool parameters, which can themselves carry sensitive arguments.

Zero data retention does not make the instance content-free in every sense:

* Aperture still records usage metrics, including identity, model, token counts, and estimated cost. These are stored separately from captured content and are not governed by the retention settings.
* Aperture does not change how the upstream provider handles your content. The request is encrypted in transit: connections over the tailnet use Tailscale encryption, and Aperture reaches upstream providers over TLS. The provider you route to still receives and processes the request, so provider-side handling remains a provider and contractual concern that retention settings do not address.

The archive-to-S3 posture is a deliberate trade-off: it keeps the instance disk clean but writes the same content to an external bucket. Treat that bucket as in-scope for the same compliance controls you applied to the instance, including access control and encryption, because the content you removed locally now lives there instead.

## Next steps

* Refer to [Privacy and data retention][kb-aperture-privacy] for an overview of how Aperture stores, retains, and exports captured data.
* Refer to the [`database` configuration reference][kb-aperture-retention] for the complete field reference.
* [Export usage data to S3][kb-aperture-export-s3] to keep a durable, off-box archive.

[kb-aperture-configuration]: /docs/aperture/configuration

[kb-aperture-dashboard]: /docs/aperture/reference/dashboard

[kb-aperture-export-s3]: /docs/aperture/how-to/export-usage-data-to-s3

[kb-aperture-get-started]: /docs/aperture/get-started

[kb-aperture-privacy]: /docs/aperture/privacy-and-data-retention

[kb-aperture-retention]: /docs/aperture/configuration#database
