On this page
- What handling personal data in an AI pipeline actually requires
- The pipeline makes copies, and the copies are the compliance problem
- The Copy Ledger
- Redaction reduces risk, it does not remove the obligation
- Embeddings, caches and fine-tunes are copies too
- What the provider boundary gives you, and what it does not
- Deletion is a system property, and a drill is how you prove it
- Answering a subject request without rebuilding the pipeline
- Definitions your engineers and your lawyers have to share
What handling personal data in an AI pipeline actually requires
It requires three things you can produce on demand: a list of every place one person's data comes to rest in your pipeline, a delete method for each of those places, and evidence that the delete method works. Everything else follows from those. The reason AI pipelines are harder than the systems around them is not the model. It is that a single request fans one record out into six or seven copies, several of which were created by a library you added for observability and never thought of as a data store.
This is the engineering half of the problem. The legal half, which is your lawful basis, your privacy notice and your contracts, belongs to whoever owns it in your organisation, and nothing here is legal advice. What engineering owns is the map, the controls and the proof. If you cannot draw the map, the legal half has nothing to stand on, because every answer becomes a description of what the system is supposed to do rather than what it does.
- 1 keyone identifier must mean one person in every store, or deletion is a full scan and a prayer
- 6 to 9resting places a single AI request typically creates, most of them added by libraries
- 2 rowsin the usual map have no delete method: the evaluation dataset and the fine-tune
- Not 100%recall on any redaction detector, which is arithmetic to run rather than a fact to accept
The pipeline makes copies, and the copies are the compliance problem
Follow one request through the system with a debugger and write down every place bytes stop moving. The architecture diagram shows three boxes. The debugger shows nine, because your logging library, your tracing tool, your error handler and your cache all made copies without asking. Each copy has its own retention, its own access control, and its own deletion story, and none of that was a decision anybody made. Deciding what belongs in those records in the first place is covered in what to log in AI systems; this guide is about what happens to the records once they exist.
| Where the copy lands | Created by | Usual retention | How you delete it | What breaks when you do |
|---|---|---|---|---|
| Prompt assembled in memory | Your application, on every request | Ends with the request, unless something logs it | Nothing to delete if it is never written | Nothing |
| Application and gateway logs | Your logging library at info level, plus the proxy in front of the provider | Whatever the platform default is, usually longer than you think | Deletion by subject key, if you indexed by subject key | Debugging older than the retention window |
| Trace and observability store | The LLM tracing tool, storing full inputs and outputs by design | A vendor default, often generous | The vendor's delete API, per trace, once you can find them | Replaying an old failure exactly |
| Error tracker breadcrumbs | An exception that carried the request body into the context | Long, and rarely reviewed by anyone | Manual, and this is the row teams forget | Nothing, which is precisely why it survives |
| Provider side logs | The model provider, per your contract and plan | Contractual. Read the agreement and the account setting | A request to the provider, on their timetable | Nothing you control |
| Prompt and response cache | Your own cache, keyed by a hash of the prompt | Until eviction, which is not deletion | Delete by key, only if the key contains a subject key | Hit rate, briefly |
| Chunk store and vector index | Your ingestion job, once per document | Until you delete it | Delete by document id, then reindex | Retrieval quality on that document, immediately |
| Evaluation and golden datasets | An engineer pasting a real failing case into a test file | Forever, in version control, replicated to every clone | Rewrite the case with synthetic data | The realism of the eval, a little |
| Fine-tuning data and the weights | A training run, months ago | Forever, inside a model artefact | Retrain from a filtered dataset | Every downstream comparison, and your schedule |
The Copy Ledger
Turn that table into a file that lives beside the code and changes in the same pull request. A privacy answer sourced from a file is a lookup. A privacy answer sourced from memory is an opinion, and it goes stale the week someone adds a caching layer.
The Copy Ledger
Six moves. The output is one file per data flow, and the finding is always in move four.
Pick the identifier that means one person across every system, and make every copy carry it. A copy that cannot be traced back to a subject key cannot be deleted on request, which means you must not create it. This single rule kills more bad logging than any policy document.
Walk a real request in a debugger, in staging, with tracing on. Write down every place bytes come to rest, including the ones a framework created for you. The list is always longer than the drawing, and the surprises are always infrastructure rather than application code.
Purpose is the field that stops scope creep, because a copy kept for debugging cannot quietly become training data if the purpose says debug. A retention clock with no enforcing job is a comment, so the row records the name of the job that enforces it.
Every row gets a delete method: an API call, a scheduled job, a partition drop, a key deletion. The rows marked none are the real output of the exercise. Each one gets fixed, or the copy stops being created, or somebody senior signs their name against keeping it.
Pick one real subject in staging, delete them through your normal path, then search every resting place for the subject key. The drill fails the first time, in a place nobody predicted, usually the error tracker or a backup. That failure is the entire value of running it.
A new tracing vendor, a new cache, a new provider, a new enrichment API. Each adds a row and each is added by an engineer who is not thinking about deletion that afternoon. Put the ledger in the pull request template so the row is written by whoever created it.
# data-map.yml, one file per flow, kept beside the code and updated in the same pull request.
subject_key: customer_id # the one identifier that means one person, everywhere
flow: support-summariser
lawful_basis_owner: dpo # engineering records this decision, it does not make it
fields:
- name: customer_email
class: direct_identifier
to_model: false # tokenised before the call, rehydrated after
token_format: EMAIL_{n}
- name: message_body
class: free_text_unbounded # may contain anything a customer chose to type
to_model: true
redaction: detector_v3
measured_recall_percent: ?? # measure this on your own held-out sample. never copy a
# vendor figure, and re-measure when the document type changes
- name: account_balance
class: financial
to_model: false # the task never needed it
copies:
- place: app_log
purpose: debug
ttl_days: 14
enforced_by: retention_policy_prod
delete: by_subject_key
- place: trace_store
purpose: incident_replay
ttl_days: 30
enforced_by: vendor_project_setting
delete: vendor_api
- place: prompt_cache
purpose: cost
ttl_days: 2
enforced_by: cache_ttl
delete: by_key # key must contain subject_key or this row is a lie
- place: vector_index
purpose: retrieval
ttl_days: null
enforced_by: deletion_worker
delete: by_document_id_then_reindex
- place: eval_dataset
purpose: regression_testing
ttl_days: null
enforced_by: none # FINDING: synthesise these cases, then close this row
delete: none
- place: provider_logs
purpose: none
ttl_days: contractual
enforced_by: agreement + account setting
delete: provider_request
checked_on: 2026-08-19 # this row expires, so record the date
drill:
subject: staging_subject_0042
last_run: 2026-08-19
places_that_failed: [error_tracker_breadcrumbs]
fix: strip request body from exception context, ticket PLAT-2214
A ledger with no gaps on the first pass means the walk was done from the diagram rather than the debugger. Expect two or three rows marked none, expect one drill failure, and treat both as the return on the exercise. The version of this document that impresses an auditor is the one with a dated fix ticket next to each gap, not the one that claims there were none.
Redaction reduces risk, it does not remove the obligation
Redaction is worth doing, and it is not a control you can lean on the way a firewall rule is a control, because detector recall is never one hundred percent on free text. Run the arithmetic on your own numbers before you describe redaction to anyone as the reason a field is safe. The second output below is the one that changes minds.
Recall is the share of real identifiers your detector catches. Measure it on your own held-out sample rather than taking a vendor figure, because recall on invoices and recall on chat transcripts are different numbers for the same tool.
At the default numbers, a detector that catches ninety eight percent of identifiers still leaves at least one identifier in roughly one document in nine. That is the shape of the problem: per-identifier accuracy sounds excellent and per-document accuracy is what a regulator or a customer actually experiences. Design accordingly, which means redaction sits alongside minimisation rather than instead of it.
If you keep a mapping that turns EMAIL_1 back into a real address, the record is still personal data and every obligation still applies. That is not an argument against tokenisation, which is one of the most effective controls available. It is an argument against writing anonymised in a document because a name was replaced by a token in one hop of a nine hop pipeline.
Embeddings, caches and fine-tunes are copies too
The three places teams forget are the three with the worst deletion stories. Each one needs a decision at ingestion time, because retrofitting the decision means reprocessing everything you have.
- Vector indexes. An embedding is derived from the text, and published work on embedding inversion has shown that meaningful parts of the original can be reconstructed from vectors alone. Treating a vector store as an anonymiser is not a position worth defending. Deletion needs a mapping from subject key to document id to chunk ids, built during ingestion, because reconstructing it later means re-embedding the corpus.
- Caches. A prompt cache keyed by hash holds the prompt in full. If the key does not contain a subject key, you cannot remove one person from it, and eviction is not deletion because you cannot say when it happened or prove it did.
- Fine-tunes. A record that entered training cannot be lifted back out of the weights. The delete method is retraining from a filtered dataset, on your schedule and at your cost, which is why the fields allowed into a training set are decided before the first run and not after the first request.
- Backups and snapshots. A point-in-time restore puts deleted records back. Either the deletion job runs against restores as part of the restore procedure, or the backup window is short and documented, and somebody has written down which of those two you chose.
- Enrichment APIs. Sending a record to a third party to append a company size or a phone number creates a copy in someone else's system and a processor relationship you now own, complete with its own row in the ledger.
Source system in seconds, chunk store in minutes, vector index after the next reindex, cache after its retention window, provider logs on their contractual timetable, fine-tune at the next training run. Write those six intervals down. The longest one is your honest answer to how long deletion takes, and discovering it during an incident is worse than discovering it in a planning meeting.
What the provider boundary gives you, and what it does not
It gives you contract terms and configuration settings. Nothing on the provider side is verified by testing, it is verified by reading, and everything in it can change without a deploy on your part. So record the claim, the evidence, and the date you last checked, then re-check on a calendar rather than on a rumour.
| The claim | What it actually is | How you verify it | What it does not cover |
|---|---|---|---|
| Your data is not used for training | A term in an agreement, sometimes tied to the plan, the endpoint or an account setting | Read the current terms for your plan, then check the setting in the account and project you actually call from | Anything your own systems store, which is most of the risk |
| Zero retention | A contractual arrangement, sometimes limited to certain endpoints or granted on application | Written confirmation plus the setting, plus the date. Read the abuse-monitoring carve-out, because there usually is one | Your logs, your traces, your cache, your error tracker |
| Data stays in region | A routing and storage commitment, which varies by region and by service within the same provider | The documented regional endpoint, and your own client configuration, which is the part that goes wrong | Where your own observability data lives, which is your problem entirely |
| It is encrypted | Transport and at-rest encryption, which is table stakes and rarely the exposure | Assume it is true and move on | Anyone with console access, which is the actual risk you were worried about |
| We hold a certification | An audit against a scope you have not read yet | Ask for the report, then read the scope section and the list of exceptions | Your implementation, completely |
Deletion is a system property, and a drill is how you prove it
A deletion path that has never been executed end to end does not work. This is not cynicism, it is the consistent result of running the exercise: something in the chain was built before the pipeline existed and nobody rewired it. Run the drill quarterly, in staging first, then once in production with a consenting internal subject.
- Create a traceable subject
Seed a staging subject whose text contains a unique, greppable token in every free-text field. A random string is better than a fake name, because you can search for it across stores without false positives and without needing exact-match support.
- Push them through the full pipeline
Upload a document, raise a ticket, trigger a summary, force an error so the exception path runs, and let a scheduled job touch the record. Errors matter most, because the error path is the one that copies the request body somewhere nobody planned.
- Delete through the normal path
Use the same route a real request would take, including any manual step. If the route includes a person doing something by hand, that person is part of the system and their step belongs in the runbook with a named backup.
- Search every resting place for the token
Every row of the ledger, one at a time, including backups and the error tracker. Anything that still returns a hit is a gap with a ticket number, not a discussion.
- Time it, then record the longest interval
The slowest store sets your true deletion time. Publish that number internally so nobody promises a shorter one to a customer, and so the next person to add a store knows what standard they are joining.
- Fix one thing and re-run
The drill is only useful if the gap list shrinks. A drill that finds the same gap three quarters running is a governance problem rather than an engineering one, and it needs to be raised as such.
Answering a subject request without rebuilding the pipeline
Access requests are answered from the same ledger as deletion requests, which is the argument for building it once. The statutory clock is set by your regime and is short, so check yours and write down who starts it, because the clock usually starts at a support inbox rather than at an engineer's terminal. The failure mode is not refusing the request. It is spending nineteen of your days discovering where the data was.
If your system produces answers from retrieved documents, the access request also has to cover what was retrieved and shown, not only what was stored. That is one more argument for keeping citation records with each response, which citations and grounding covers from the quality side and which turns out to pay for itself twice.
Definitions your engineers and your lawyers have to share
Most arguments in this area are two teams using one word for two different things. Agree these five in writing, then use them consistently in tickets, in the ledger and in customer answers.
- Personal data
- Any information relating to an identified or identifiable person. The test is whether someone can be singled out using that data plus anything else reasonably available, which is why a pseudonymised record stays personal data for as long as the mapping exists.
- Pseudonymisation
- Replacing identifiers with tokens while keeping a separate mapping that can reverse the replacement. It reduces risk substantially and it does not take the record out of scope, because the mapping exists. Almost all AI redaction is pseudonymisation.
- Anonymisation
- Removing the ability to single out a person permanently and irreversibly, including by combining the data with other available sources. Genuinely anonymised data falls outside the rules, which is exactly why the bar is high and why free text rarely clears it.
- Data minimisation
- Sending only the fields a task actually needs. In an AI pipeline it is the cheapest control available, because a field that never reaches the model cannot leak from a prompt, a log, a trace, a cache or a provider.
- Processor
- An organisation that handles personal data on your instructions rather than for its own purposes. Adding a model provider, a tracing vendor or an enrichment API adds a processor, and each one adds a row to your record of processing and a row to the ledger.
Two habits keep this alive after the first push. Add the ledger row in the same pull request that creates the copy, and re-run the deletion drill on a calendar rather than after an incident. If you want the map, the drill and the guardrails built as one piece of work on a system already in production, that is evaluation and guardrails, and it pairs with the pre-ship review in security questions to answer before you ship AI.
Questions readers ask next
Does redacting personal data before the model call make us compliant?
Are vector embeddings personal data?
What do we do about personal data already inside a fine-tuned model?
Do we need a data protection impact assessment for an internal AI tool?
Is it safer to run a model in our own infrastructure?
How long should we keep prompts and completions?
ChatGPTalker. "How to Handle Personal Data in an AI Pipeline." chatgptalker.com, 2026-08-26. https://chatgptalker.com/guides/personal-data-in-ai-pipelines/