Skip to main content
Data Privacy

Zero data retention architecture for AI products

Zero retention is a property of a request path, not a clause in a data processing agreement. Here is where copies actually accumulate, why delete does not delete, what encryption keys buy you that delete scripts cannot, and how to prove the claim on a payload you can trace.

What the security questionnaire is actually asking

The line appears in every enterprise review: describe your data retention, and state whether customer content persists on your systems after a request completes. The honest answer for most AI products is yes, in about ten places, and three of those came from a library default nobody has looked at since. Zero data retention is not a toggle and not a paragraph you paste into a contract. It is a property of an entire request path, and you hold it only if you can name every store a payload touches and say what happens to it in each one.

The claim ships ahead of the system because the claim is cheap. A page saying customer data is never stored costs an afternoon of copywriting. The system underneath costs a redaction layer, a key hierarchy, a retention register, TTLs enforced in code rather than described in a policy, and a test that follows one payload through production and proves it is gone. When the words go first, the gap gets found by an auditor sampling your logs, or by a customer's engineer who spotted their own text in a support ticket screenshot. Neither conversation has a good version.

Be precise about the phrase, because two different promises travel under it. One is about your systems: content is held for the life of the request and never written to durable storage. The other is about your subprocessors, the model provider first among them: content sent onward is not retained on their side either. Customers usually mean both and ask about one. Answer both in writing, before anyone thinks to ask.

You are probably here because

  • A security questionnaire is sitting open asking where customer content is stored and for how long, and answering it honestly means asking three different teams.
  • Your site already says customer data is never stored, and nobody has traced a real request through production to check whether that is true.
  • A customer asked what happens to their content in your backups, and “we delete it” stopped feeling like a complete answer.

These usually share one root cause — nobody has written down every store a single request touches — which is what the retention register below is for, and the canary test near the end is how you find out whether the answer holds.

Four classes of data, and they do not get the same answer

Content. Prompts, uploaded files, retrieved passages, tool inputs, model output. This is what the customer means by their data. It is the easiest class to define and the hardest to keep out of the places it does not belong.

Derived artifacts. Embeddings, extracted entities, summaries, index structures, cached completions, evaluation sets built from real traffic, fine-tuned weights. Teams treat these as a separate category because they look like numbers rather than text. They are content in a different encoding, and any competent reviewer will treat them that way. A working test: if an engineer with access to the artifact could reconstruct something the customer would recognize as theirs, it is content.

Operational metadata. Request IDs, tenant IDs, timestamps, model name, token counts, latency, status codes, error classes. You need all of it to operate the product, and none of it has to contain a single character the customer typed. Keeping that boundary sharp under deadline pressure is most of the discipline.

Records you are obliged to keep. Authentication events, administrative actions, billing history, security-relevant logs. Retention here is not optional, and a deletion promise written broadly enough to swallow the authentication log will fail the same SOC 2 report the customer asked you to produce. ISO 27001 in its 2022 revision has an explicit control for information deletion, and it sits alongside controls that require you to retain evidence. Those two obligations meet in your retention register, not in a meeting during the audit.

Almost every argument about zero retention is really an argument about class two. Nobody objects to holding a request ID. What surprises customers is finding that their document is still recoverable from a vector index, or that a model was tuned on their support tickets. Decide the disposition of derived artifacts explicitly, write it down, and put it in the contract, because the reviewer who finds it later will assume the omission was deliberate.

Write the retention register before you write any code

The register is one table with a row for every place a byte can land: the store, the class it holds, the TTL, the mechanism enforcing that TTL, the owner, and the date somebody last verified it. It reads like paperwork and it is the highest-value artifact here, because it turns a vague promise into a finite list of engineering tasks. Two rules make it worth keeping. Every row names a mechanism rather than an intention, and something automatic checks the register, so a new bucket or topic cannot appear without showing up as an unowned row.

StoreWhat it ends up holdingWhat a delete actually doesThe control that works
Application logsWhole request bodies once someone adds a debug line during an incidentNothing until the log platform's retention window expiresStructured logging with an allowlist of fields, plus a retention setting you own
Error trackerRequest bodies, headers, and local variables captured from stack framesPer-event deletion exists, but nobody knows which events to deleteScrub in the before-send hook and disable frame-local capture
Relational databasePayloads parked in a table added to debug a launchMarks rows dead; data remains in pages, WAL, replicas and snapshotsDo not write it, or encrypt per tenant and destroy the key
Object storeUploads, exports, model artifacts, log archivesAdds a delete marker when versioning is on; the version persistsLifecycle rules on noncurrent versions, and a check that they exist
Queues and dead lettersExactly the payloads that failed, which is the worst possible subsetConsumption is not deletion; retention is a topic settingExplicit retention on every topic, TTL on every dead-letter store
Cache and vector indexCompletions, embeddings, chunk text kept as index metadataSoft delete; segments hold the data until a merge runsTTL at write time, forced merge on delete, tenant-scoped keys
Backups and snapshotsA copy of everything above, on a slower clockNothing selective is possible inside a snapshotEnvelope encryption with per-tenant keys, then destroy the key

Audit Order — Where We Look First for Retained Content

Error tracker and crash reporting
94
Dead-letter queues and retry buffers
88
Application and access logs
86
Vector index and cache entries
78
Backups, snapshots and point-in-time windows
74
Product analytics and session capture
62

Our default search order when starting a retention audit. A prioritization judgment, not a measurement of any particular system.

Delete does not delete

Every storage engine implements deletion as a bookkeeping operation, and physical removal happens later on a schedule that belongs to the engine rather than to you. That is a design choice, not a defect: immediate erasure would make writes slow and crash recovery unsafe. It also means the word delete in your policy document maps to nothing in particular until you name the mechanism under it.

Relational databases. A delete in Postgres marks the tuple dead. The row version stays in the heap page until autovacuum reclaims it, the change is in the write-ahead log, the log segment is in the archive, and the archive is what point-in-time recovery reads. A typical managed instance keeps a recovery window of a week to about a month. That window is the floor on your deletion timeline unless you change the mechanism, and no amount of careful SQL moves it.

Object storage. With versioning enabled, deleting an object writes a delete marker and keeps the previous version. Everything looks gone through the console and the API, and the bytes remain until a lifecycle rule expires noncurrent versions. Worse, object lock in compliance mode makes deletion impossible for the retention period by design. That control exists to defend against ransomware, and it fights your deletion promise directly. Pick which one governs each bucket, deliberately, and write the reason next to the row in the register.

Log-structured queues. Kafka keeps messages for the topic's retention setting whether or not anyone consumed them, and the default on a fresh cluster is measured in days. Compacted topics are worse: they keep the latest value per key indefinitely, and removing one requires publishing a tombstone and then waiting out a second timer before compaction actually drops it. Any topic carrying request payloads is a content store with a long memory.

Caches. A key written without an expiry lives until eviction pressure or a restart, and if persistence is on, it is written to a snapshot file or an append-only file on disk. The moment persistence is enabled, the cache is durable storage that nobody put in the register.

Search and vector indexes. Deletes are soft. The document sits in an immutable segment marked for removal and disappears when a merge rewrites the segment, which may be a long time on a cold index. If your deletion path is a delete API call and nothing else, the data outlives the acknowledgement by an unbounded interval.

Delete is a statement of intent. Vacuum, lifecycle expiration, segment merges and key destruction are the operations that actually remove data, and each one runs on a clock you have to set.

Three surfaces that leak with default settings

The error tracker. This is the most common finding, and it is almost always a default. Crash reporting SDKs attach request bodies and, in many configurations, the local variables of each stack frame. A team that carefully redacts its logging path frequently has no redaction at all on the exception path, because they are different code. Scrub in the before-send hook where you can see the whole event, turn off frame-local capture for any function that handles a payload, and verify by throwing a deliberate exception with a marker string in it.

Query strings. Anything in a URL is in the load balancer log, the CDN log, the reverse proxy log, the browser history, and the referrer header sent to any third party the page talks to. Putting a search phrase or a document identifier built from customer text into a query parameter distributes it to five systems you did not design. Content goes in the request body without exception, and identifiers are opaque.

Replay paths. Dead-letter queues, retry buffers, webhook redelivery stores, and the failed_requests table someone added during launch week. These hold precisely the payloads that failed, they were created as temporary, and temporary things do not get TTLs. In our experience this is the densest concentration of retained content in a typical system, and it is invisible from the architecture diagram because nobody draws the error path.

Product analytics belongs on the same list. Session replay tools record the DOM, which includes whatever the user typed, and masking is opt-in on most of them. A privacy claim that covers the backend but not the analytics script is not a privacy claim.

The model layer has its own retention, and its own exceptions

Model providers publish a default retention window for abuse monitoring, commonly measured in days, and offer a zero-retention configuration to approved accounts. Three questions decide whether that configuration means what you need it to mean. Which endpoints does it cover, which product features are excluded, and is the specific model you want even available under it? That last one catches teams by surprise: some capabilities are offered only with retention enabled, and discovering that after you have built the product around one is an expensive rewrite.

Prompt caching deserves its own line. Caching a stable prefix cuts cost and latency substantially, and it works by holding part of your request on the provider side for a short interval. That is a retention surface with a timer on it. Whether it is compatible with your zero-retention configuration is a question for the provider's current documentation and your account terms, and the answer changes as products evolve.

Every adjacent endpoint needs the same check. Batch processing, file upload, evaluation tooling and provider-side dashboards each have their own storage behavior, and an agreement covering the completion endpoint but not the file endpoint is worse than none, because it makes everyone stop looking.

Evidence Practice

Snapshot the provider's terms with a date, not a link

Provider retention pages change. When an auditor asks what your data handling looked like in a given quarter, a live URL answers the wrong question. Keep a dated capture of each subprocessor's retention and security page with your other control evidence, and refresh it on the cadence of your access reviews. Five minutes a quarter, and it is the difference between an answer and an apology.

Embeddings and fine-tunes are content

An embedding feels like anonymization. It is a vector of floats with no readable text, and it is tempting to treat the vector store as metadata. Published research has shown that short input texts can often be reconstructed from their embeddings alone, given access to the same embedding model. Treat vector rows exactly as you treat the source documents: same tenant scoping, same TTL, same deletion path, same encryption. And remember that most vector stores delete softly, so the deletion path has to include whatever forces a compaction or merge.

Fine-tuning is harder, because there is no deletion path at all. Weights memorize, and no operation removes one customer's contribution short of retraining without their data. If you tune on customer text, the model is a retention surface your delete job cannot reach, and the honest options are narrow: per-customer adapters you can destroy independently, or no training on customer content. Deciding that during a renewal is much worse than deciding it now.

You cannot delete a fact out of a set of weights. Decide that before you fine-tune on customer text, not during the renewal.

One more derived artifact goes unnoticed for years: the evaluation set. Someone builds a golden set from real traffic because synthetic examples were not representative, it lands in the repository, it gets cloned to laptops, and it shows up in CI logs whenever a test fails. Evaluation data built from customer content needs the same disposition as production content, and it needs it written down, because the repository is the one store where a retention policy has no natural enforcement point.

Backups are where most promises die

Your deletion timeline cannot be shorter than your backup retention if deletion means removing rows. A thirty-day recovery window and a seven-day deletion commitment are contradictory, and any auditor who reads both documents will notice. There are three ways out. Shorten the backup window, which trades away your own recovery posture. Exclude the content store from backups entirely, which works for genuinely reconstructible caches and indexes and nothing else. Or change what deletion means.

That third option is the one that scales, and it is envelope encryption with per-tenant keys. Each tenant, or in the strictest designs each record, gets a data encryption key. That key is stored wrapped by a key in a managed key service, and the plaintext key exists only inside a process for the duration of a request. Deleting the key renders every ciphertext copy unreadable at once, in the database, in the object store, in the replica, and in every snapshot ever taken. The industry calls it crypto-shredding, and it is the only mechanism that reaches inside a backup.

Four details decide whether it actually works. The unwrapped key must not be cached in a process that outlives the deletion, so key caches need short TTLs and an invalidation path. Managed key services impose a waiting period before a key is destroyed, typically a minimum of seven days and configurable up to about a month, so your deletion service-level commitment has to be longer than that window. The key store must not be backed up on the same schedule as the ciphertext, or a restore brings back both. And you need a way to show the key is gone, which means the key service's audit trail is part of your deletion evidence.

Crypto-shredding does not save you everywhere. A search index built from plaintext, a cache keyed on content, a log line written before encryption, and anything a subprocessor holds are all outside its reach. Those stores need real deletion or need to never receive content in the first place, which is why the architecture below pushes redaction as far forward as it will go.

Engineering Effort — Where a Zero-Retention Build Spends Its Time

Key hierarchy and envelope encryption
26
Redaction at ingress and the single egress path
22
Rebuilding support and debugging without content
19
Deletion service, certificates and audit trail
15
Canary testing and continuous verification
11
Contract language, evidence and subprocessor review
7

A planning split for a retrofit on an existing product, summing to 100. Greenfield shifts effort out of the first two rows and into the third.

The architecture that holds

One egress point. Every call that leaves your boundary carrying customer content goes through a single service. Two SDK call sites means two redaction implementations, and one of them is behind. This service owns the provider credentials, the redaction pass, the token accounting, and the audit record, and nothing else in the codebase is allowed to import the provider SDK.

Redact at ingress, not at the sink. Detection runs once, at the edge, and everything downstream sees placeholder tokens with a mapping held in request-scoped memory. Redacting at each sink means every new sink is a new hole, and there is always a new sink. Pattern-based detection handles the structured identifiers, a named-entity pass handles names and locations, and the mapping is discarded when the response is written.

Request-scoped memory. Content lives in process for the life of the request. No temp files, no debug dumps, no staging table, no local disk. This is a code review rule as much as an architectural one, and it is the rule that gets violated first during an incident, which is why the canary test below runs continuously rather than once.

TTL by default at the infrastructure level. Every bucket has a lifecycle rule, every topic has a retention setting, every cache write sets an expiry, every log stream has a window. Make the absence of a TTL a failure in your infrastructure-as-code checks, so a new store cannot reach production without someone declaring how long it keeps things.

Per-tenant keys from the first schema. Retrofitting envelope encryption onto a year of production data is the most expensive item on this page. The key hierarchy costs a week at the start and a quarter later.

Deletion as a job, not a script. It has an identifier, a status, per-store results, retries, and an emitted certificate recording what was deleted and when. A script someone runs by hand cannot produce evidence, and evidence is what the customer is buying.

Separate paths for content and metadata. Dashboards, alerts, billing and support tooling read the metadata path only. If an operational tool needs content to be useful, that is a design problem, not a reason to widen the pipe.

Send it over and we will tell you what we would change.

Email the list of stores one request touches, your backup and point-in-time recovery windows, and the deletion window you have already promised in writing to contact@precisionfederal.com. You get back a short written note naming the three things we would change and why. One business day. No charge, no meeting, no deck.

contact@precisionfederal.com

What you keep instead of the content

The objection engineers raise, correctly, is that you cannot debug what you cannot see. The answer is to keep structure and drop values, which turns out to cover most of what debugging actually needs.

Keep shapes: field names, types, lengths, counts, detected language, whether a required field was empty, how many chunks the retriever returned and what their scores were. Keep hashes for correlation, computed with a keyed HMAC rather than a bare digest, so that a hash of a short value like an email address is not trivially reversible by a lookup table, and rotate the key on a schedule. Keep error classes and stack positions with frame locals disabled. Keep the full timing breakdown, because latency questions are the most common support questions and they need no content at all.

Then build a reproduction harness. Given the structural fingerprint of a failed request, generate a synthetic document with the same shape, the same field lengths, the same number of pages and tables, and run it through the pipeline. Most retrieval and extraction failures reproduce on shape alone. The ones that do not are the cases where you ask the customer for a sample under an explicit, time-boxed consent, and you delete it when the ticket closes. Set that expectation in the support policy from day one rather than inventing it during an outage.

Be candid internally about the cost. Some tickets will take longer to resolve. Teams that promise zero retention and then quietly keep a debug log have chosen the worst of both: the support burden of the promise and the exposure of the log.

Proving it: the canary test

Every claim in this article is verifiable, and none of it is verified by reading the code. Generate a unique high-entropy token, put it inside a realistic payload, and send it through the production path exactly as a customer would. Then go looking for it. Search the log platform, the error tracker, the database including the WAL archive, the object store including noncurrent versions, every queue and dead-letter store, the cache, the search and vector indexes, the analytics warehouse, and a backup restored into a scratch environment. Do this at one hour and again at forty-eight, because some of the failure modes are on a delay.

A retention claim nobody has tried to break is a hope. Plant a canary through the real request path, then go looking for it in every store forty-eight hours later.

Run the fast half of that sweep on a schedule and fail the build when it finds something. Run the backup restore quarterly, because it costs real money and it is the check people skip. The first time we run this against a system that has never had it, it finds something, and the finding is almost always in a store nobody listed when we asked where data goes.

What has to exist before you make the claim

  • A retention register with a mechanism, an owner and a verification date on every row
  • One egress service, with the provider SDK importable from nowhere else
  • Redaction at ingress, with a test that throws a deliberate exception carrying a marker
  • Per-tenant data encryption keys, wrapped in a managed key service with an audit trail
  • A deletion job that emits a certificate naming each store and its result
  • A canary sweep in continuous integration, plus a quarterly restore-and-search of a backup
  • A subprocessor list stating what each one retains, with dated evidence captures
  • Marketing copy and the data processing agreement saying the same thing

Where teams get this wrong

  • Promising deletion in seven days with a thirty-day point-in-time recovery window still enabled
  • Redacting the logging path and leaving the exception path untouched
  • Treating embeddings and cached completions as metadata because they are not readable text
  • Signing a zero-retention agreement that covers one endpoint and building on three
  • Leaving the dead-letter queue and the retry buffer without any retention setting
  • Fine-tuning on customer content and discovering there is no delete path for a weight
  • Backing up the key store on the same schedule as the ciphertext it protects

The promise you can actually keep

Retention is a product tier, not a binary, and treating it as a ladder lets you sell each rung honestly. The default tier keeps content for an operational window because it makes support and quality work cheap. The strict tiers cost more to build and more to run, and enterprise buyers pay for them, which is the part most teams miss when they treat privacy work as pure overhead.

TierWhat you are promisingWhat it takes to buildWhat it costs you
Operational retentionContent held for a stated window, then deleted on a scheduleTTLs everywhere, a register, a working delete pathLittle. This should be your floor, not a tier
Configurable retentionThe customer picks the window, down to a documented minimumPer-tenant retention settings enforced at every storeComplexity in every deletion and reporting path
Zero retentionNothing durable beyond the request, including at subprocessorsIngress redaction, single egress, request-scoped memory, provider agreementSlower support, higher token spend, real engineering time
Customer-held keysThey can make their data unreadable without asking youExternal key management integration and a graceful revoked-key pathAn operational failure mode you do not control

Whatever tier you sell, the contract has to say six things: the deletion window in days, what deleted means including whether cryptographic destruction counts, which records survive deletion and why, the subprocessor list with each one's retention behavior, the availability of a deletion certificate on request, and a commitment to notify before a subprocessor changes. Under GDPR the erasure right in Article 17 and the storage-limitation principle in Article 5 both point at the same engineering work, and the record-keeping duty in Article 30 is essentially the retention register in legal form. If you build the register, most of the compliance paperwork writes itself from it.

What it costs, honestly

Redaction at ingress adds latency. A pattern-based pass over a typical request is small enough to disappear into network variance; a model-based entity detector is heavier and belongs behind the same cache and batching discipline as the rest of your inference. Zero retention usually means no server-side conversation state, so multi-turn sessions resend context and input token spend rises with conversation length. That is a real bill and it should be in the tier's pricing.

The engineering is measured in weeks, and the largest line is not the encryption. It is rebuilding the support workflow to run on structure instead of content, which touches runbooks, on-call habits and the expectations of the people answering tickets. Budget for it, or the redaction layer grows an exception for the support team, and the exception becomes the architecture.

Thirty days to a claim you can defend

Retention Sprint

1
Build the register by tracing one real request through every service and store
Days 1–4
2
Run the first canary sweep and record what it finds, before changing anything
Days 3–7
3
Close the default leaks: error tracker, query strings, dead letters, analytics
Days 6–14
4
Consolidate egress behind one service and move redaction to ingress
Days 10–20
5
Stand up the key hierarchy and the deletion job that emits a certificate
Days 16–26
6
Automate the canary, restore a backup and search it, then write the contract text
Days 24–30

Thirty days works because the unknowns are measurable inside it. Whether content reaches your error tracker is a test. Whether a delete removes a row from a restored snapshot is a test. Whether your provider agreement covers the endpoints you call is a document you can read this afternoon. What runs longer is the support rebuild and the key migration on existing data, and knowing that on day thirty with a costed plan beats finding it out during a security review with a signature waiting.

Bottom line

Zero data retention is an engineering property with a small number of mechanisms behind it: TTLs enforced by infrastructure, redaction at the edge, one egress path, per-tenant keys for the copies you cannot reach, and a test that tries to find the data anyway. Classify content, derived artifacts, operational metadata and required records separately, because they get different answers. Write the register first. Then make the claim, in language that matches what the register says, and keep the evidence that proves it.

Frequently asked questions

What does zero data retention actually mean for an AI product?

That customer content exists only for the life of the request and is never written to durable storage, in your systems or in your subprocessors'. It does not mean you keep nothing. Request IDs, timestamps, token counts and error classes are operational metadata and can be retained without holding any content the customer typed.

How do you delete customer data from backups?

You do not delete from inside a backup. You encrypt each tenant's data with its own key, keep that key in a managed key service, and destroy the key when the customer leaves. Every ciphertext copy in every snapshot becomes unreadable at once. Managed key services impose a waiting period before destruction, usually at least seven days, so your deletion commitment has to be longer than that.

Are embeddings considered personal data?

Treat them as content. Published research has reconstructed short input texts from their embeddings when the same embedding model is available, so a vector store is a content store in a different encoding. Give vector rows the same tenant scoping, TTL, encryption and deletion path as the source documents, and make sure the deletion path forces the merge that actually removes the segment.

Can you still debug a system that retains nothing?

Mostly, if you keep structure instead of values: field shapes, lengths, counts, retrieval scores, timing breakdowns, error classes, and keyed hashes for correlation. Build a harness that generates a synthetic document matching the structural fingerprint of a failed request. The remainder are handled by asking the customer for a sample under explicit, time-boxed consent.

How do you prove a deletion actually happened?

Two artifacts. A deletion job that emits a certificate naming each store, the action taken and the timestamp, backed by the key service's audit trail when crypto-shredding is used. And a canary test: send a unique token through the production path, then search every store in the register, including a restored backup, and confirm it is not there.

1 business day response

Making a retention claim you will have to defend?

We build the register, the redaction and egress layer, the per-tenant key hierarchy and the canary test, or we review the architecture you already have and tell you where the copies are. Email contact@precisionfederal.com with your stack and the promise you want to make, and we will come back with a scoped answer.

Email contact@precisionfederal.comCapabilitiesMore insights →
UEI Y2JVCZXT9HP5CAGE 1AYQ0NAICS 541512SAM.GOV ACTIVE