Data handling
What Atlas retains, for how long, and what it never does with your content.
This page is written to be checkable rather than reassuring. Each claim names the control that makes it true.
The short version
Prompts
Not retained. Not past the response.
Completions
Not retained. Including any reasoning prelude.
Training
Never. Customer content is not used to train models.
What is retained
| Data | Retained? | For how long |
|---|---|---|
| Prompt content | No | Not past the response |
| Completion content, including a reasoning prelude | No | Not past the response |
| Diagnostic capture — per request, caller-flagged | Yes | At least 24 hours, never more than 25 |
| Request id, organization, model, token counts, timings, outcome | Yes | Indefinitely |
| Account records — organizations, users, memberships, roles | Yes | Life of the account |
| API key hashes, prefixes, labels, last-used timestamps | Yes | Until revoked and pruned |
| Audit log, including every read of a diagnostic capture | Yes | Indefinitely, append-only |
| Logs, metrics, traces | Yes | Per operator retention settings — allowlisted fields only, never content |
There is no retention setting
Per-organization opt-in retention is deferred, and so is any control for electing it. There is no toggle in the console and no field on the API.
This is a deliberate absence, not an unimplemented feature. A toggle with no store behind it would tell an owner their content is retained when it is not, which is worse than not offering the choice at all.
Three separate things would have to change before any surface could retain content:
- The retention policy is a frozen constant with no setter anywhere in the codebase.
- The diagnostic capture table has a database
CHECKconstraint bounding every row's own window to the published one. A writer with direct SQL access — an Atlas operator included — cannot store a capture with a 30-day expiry. - No other table has a column that could hold content, and an automated audit sweeps every table in the database after a completed request to prove it.
How zero retention is enforced in logs
The control is a field allowlist at every boundary that can see a request body — not a denylist, because a denylist fails open on every field nobody thought of, and the fields nobody thinks of are the ones added next.
| Boundary | Control |
|---|---|
| Logger | Only allowlisted field names, and only values matching each field's declared kind. An unlisted field is dropped, and the drop is counted. |
| Log messages | Not free text — a constrained event name. An interpolated message becomes event.unnamed. |
| Error reporter | The report is constructed from allowlisted fields. error.message is never read; the stack's header line is stripped. |
| Metrics | Label names come from a low-cardinality subset; request_id is deliberately not a permitted label. |
| Traces | Span names and attributes go through the same two checks. |
Values are checked as well as names, because an allowlist over names alone still passes a prompt written into a permitted field.
Tenant isolation
Request and response content, and any server-side state derived from it — including prefix and KV caches — is scoped to a single organization. It is never shared with, or observable by, another.
This is enforced at the database level with row-level security scoped per transaction, not by application filtering, and there is an automated isolation suite that asserts it.
Infrastructure providers
Atlas requires every infrastructure provider in its serving path to be bound to the same no-retention default and the same no-training guarantee described here. That requirement is not yet met, and this is the honest status of it.
| Provider | Role | In the serving path | Sees content | Recorded terms |
|---|---|---|---|---|
| Inference backend host | Model execution | Yes | Every prompt and every completion | None recorded — open |
| RunPod | GPU infrastructure and the HTTPS proxy in front of the backend | Yes | Every prompt and completion in transit, and the host they run on | None recorded — open |
| PostgreSQL host | Diagnostic captures, metering, accounts | Yes | Captured content only, for the capture window | None recorded — open; production host undecided |
| Redis host | Admission-control counters | No | No content — counters keyed by organization and model | None recorded — open |
| WorkOS | Identity: users, organizations, memberships, sessions | No | No prompt or completion content; holds user records | None recorded — open |
The inference vendor sees every prompt and every completion. That is the normal path for every request, not an edge case.
No provider in the serving path has recorded data-processing terms yet — no zero-retention commitment and no no-training commitment is on file. That is an open item, not a passing state.
Nothing on this page should be read as an absolute guarantee about a third party Atlas does not operate. What Atlas can state is what it enforces on its own systems, and what it has bound its providers to in writing.
Ask your Atlas contact before sending production content you could not send to an unbound processor.
Credentials are never captured
Even in a diagnostic capture, credential-bearing
headers are removed before anything is written — authorization,
proxy-authorization, authentication, cookie, set-cookie, api-key, and
others. This is enforced in the application and by a database constraint,
because neither is trusted to be the only control.
Audit
Every read of a diagnostic capture is recorded in an append-only audit log with the acting identity and a timestamp — including reads by Atlas operators. So are membership and role changes.
What this means for you
- You cannot ask Atlas to show you a past prompt. It does not exist. If you need one for debugging, flag it at request time — see Diagnostic capture.
- Keep your own logs if your application needs a record of what it sent. Atlas is not that record.
request_idis the handle for everything else. Token counts, timings, outcome, model version, and cost are all retained and queryable against it.