When teams add an LLM to a feature, the easiest data-flow design is also the riskiest: serialize the whole record and let the model sort out what matters. It works in a demo. In production it means customer names, emails, account numbers, and free-text notes flow to a third-party API, into your request logs, into your traces, and possibly into your eval datasets. Each of those is a place the data can leak from.
The engineering principle that helps is old: data minimization. Send only what the task needs, in the least sensitive form that still lets the model do the job.
Ask what the task actually needs
Take a support-reply drafting feature. Does the model need the customer's email address? Almost certainly not. Their first name, for the greeting? Probably. The last four digits of a card, to confirm which one is meant? Maybe. Write this down per feature as an explicit allowlist of fields, and build the prompt from that allowlist rather than from the raw record. A new column added to the database next quarter then does not silently start flowing to the model.
Pseudonymize with reversible placeholders
Often the model needs to *distinguish* entities without knowing who they are. Replace each sensitive value with a stable placeholder before the call and keep the mapping on your side:
Maria Okaforbecomes[PERSON_1],maria@example.combecomes[EMAIL_1].- The same value always maps to the same placeholder within one request, so the model can still reason about "PERSON_1 wrote to PERSON_2".
- After the response comes back, substitute the real values in for display.
A few details decide whether this works:
- Redaction is detection, and detection is imperfect. Regexes catch emails and phone-like patterns; names and addresses in free text need more. Measure recall on a sample of real, reviewed data, and treat a miss as an expected event, not a surprise.
- Placeholders must survive the round trip. Instruct the model to copy them verbatim, and validate the output: every placeholder in the response should exist in your mapping. An unknown one means the model invented it, which you should catch before a customer sees
[PERSON_7]. - Keep the mapping out of logs. If you log the mapping next to the redacted prompt, you have rebuilt the original data with extra steps. Log the redacted version; store the mapping only for the lifetime of the request.
Watch the side channels
Minimizing the prompt does not help if the data escapes elsewhere. Check your tracing and observability tooling, error reports that capture request bodies, cached responses, and datasets exported for evals. A "temporary" debug log of full prompts is a classic way for sensitive data to end up retained for months.
Know what you are not solving
Pseudonymization reduces exposure; it does not make a prompt harmless. Context can re-identify a person ("the only customer in the city with this plan"), and some tasks genuinely need the real value. For those, the answer is a deliberate decision with a reviewed vendor agreement and a retention policy, not a default.
The practical test is simple: pick a random production prompt from your logs and read it as an outsider. If you would be uncomfortable with that text in a screenshot, the next step is not a policy document. It is a smaller prompt.
Comments (0)
No comments yet — be the first.
Sign in to leave a comment.