Configure zero-retention mode
Last validated:
Use of Aperture is governed by the Aperture Beta Terms.
By default, Aperture captures request and response bodies so you can browse them in the dashboard. The retention settings let you shorten or eliminate how long that content is kept. This guide shows you how to put an instance into zero-retention mode, 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-retention mode entirely through the Aperture configuration, with no code changes required.
Prerequisites
Before you begin, ensure you have the following:
- An Aperture instance with at least one provider configured.
- Admin access to the 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 block:
durationsets the retention window. The special value"0"means zero local retention. For non-zero values, the minimum is one hour and the maximum is 3650 days (10 years).purgelists which categories of data the purge removes.require_exportoptionally 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 is already configured. The require_export gate only purges content once an export succeeds.
Step 2: Back up the current configuration
Open the Aperture dashboard and go to Administration > Configuration.
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:
"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 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 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:
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.
- 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
databaseblock. - Send a normal request through the instance.
- In the dashboard's logs or session view, 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 is configured and succeeding.
Security considerations
Zero-retention mode 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-retention mode 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 the
databaseconfiguration reference for the complete field reference. - Export usage data to S3 to keep a durable, off-box archive.
- Observe and export AI usage for an overview of Aperture's data handling.