The privacy of a system with models is decided where the copies end up
When a company puts a language model in front of its own data, the privacy risk rarely lies in the model: it lies in the copies. The text of the question ends up in a log, the passages of the documents in an index, the answer in a cache, everything in a backup. Each one is a processing of personal data with its own rules, and the principle of "privacy by design" consists in deciding, before building, which copies exist, for how long and with what protection. This article translates that principle into choices and into two programs, and says clearly where the rule ends and where the work of your adviser begins.
No part of this text is legal advice. The articles of the regulation are quoted from the official text, consulted on 2026-11-13; what I could not verify is declared as such.
Where personal data sits in a system with a model
The first exercise is the inventory. For every point where a text with personal data is written, ask yourself who can access it, how long it stays, and whether you can delete it for a single person.
- The prompt: the user's question and the context the system adds to it, often with names, amounts and addresses.
- The document index: the passages of your files, copied as text and as a vector into a separate store.
- The answer cache: useful to save time, it contains answers built with those passages.
- The request log: it serves to diagnose errors and to account for what happened, and it tends to grow without limit.
- The backups: they contain everything else, for the whole retention period.
The first four items are under your programming control, and each has a choice: not writing it, writing it in reduced form, or writing it with an expiry. The fifth is under organizational control, because a copy is deleted only when it expires. A well-made system starts here: the log, for example, can contain only the fingerprint of a question and the outcome, not the text, and this decides how large the problem to be managed later is.
What the regulation asks, in a few verified lines
Regulation (EU) 2016/679 has few articles that weigh on a system of this kind. Article 5 sets the principles: data must be "adequate, relevant and limited to what is necessary" (data minimisation), kept in identifiable form no longer than necessary (storage limitation) and processed with appropriate security. Article 25 asks for appropriate technical and organisational measures, citing pseudonymisation as an example, and, "by default", that only the data necessary for each specific purpose are processed, with regard to the amount collected, the extent of processing, the period of storage and accessibility.
Article 32 asks for a level of security appropriate to the risk and cites, among the measures, pseudonymisation and encryption, the ability to restore availability of data and a process for regularly testing the measures. Article 28 concerns whoever processes data on your behalf: it asks you to choose processors providing sufficient guarantees and to govern the relationship with a contract or other legal act, and it requires the processor not to engage another processor without your authorisation. It applies to an API provider as to the server provider: whoever hosts the machine on which the data runs is a party that has to be fitted into the picture.
Article 35 requires an impact assessment before processing that is likely to result in a high risk, in particular with new technologies. Paragraph 3 lists three cases in which it is required: the systematic and extensive evaluation of personal aspects based on automated processing on which decisions are based that produce legal or similarly significant effects; processing on a large scale of special categories of data; the systematic monitoring of a publicly accessible area on a large scale. An internal assistant on technical manuals probably does not fall within them; one that handles health or personnel data may. The assessment is done with the data protection officer, if there is one.
Pseudonymize before writing
Article 4 defines pseudonymisation as processing in such a manner that the data can no longer be attributed to a specific data subject without additional information, kept separately and subject to technical and organisational measures. Recital 26 adds a point that surprises many: pseudonymised data remain personal data, because they could be attributed to a natural person by the use of additional information. Pseudonymization reduces the risk, it does not remove the obligation: the principles do not apply only to anonymous information in the proper sense, that is, information that cannot be linked to an identifiable person by means reasonably likely to be used.
The program below applies pseudonymization to a text with three types of data: email, IBAN and the Italian tax code (codice fiscale, CF). There are two design details. For the IBAN the form is not enough: the mod 97 check of the ISO 13616 standard discards sequences that look like an IBAN but are not, like the order code in the test text. The tax code is checked only for form, without verifying the check character, and I state it: a false positive here is acceptable, a false negative is not. The token is a keyed HMAC code: the same value always gives the same token, so the cleaned text keeps the possibility of telling that two mentions concern the same person.
"""Pseudonymize a text before it reaches a log, a cache or an index.
INVENTED data. The test key sits in the code only to make the example
reproducible: in a real system it lives outside the repository, in a secrets manager.
"""
import hashlib
import hmac
import re
KEY = b"test-key-do-not-use"
EMAIL = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}")
IBAN = re.compile(r"\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b")
CF = re.compile(r"\b[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]\b") # the FORM only, no check
def iban_valid(iban):
"""Mod 97 check (ISO 13616): move the first 4 characters to the end,
replace letters with numbers (A=10...Z=35), the remainder must be 1."""
s = iban[4:] + iban[:4]
n = int("".join(str(int(c, 36)) for c in s))
return n % 97 == 1
def pseudonym(value, kind):
"""Stable pseudonym: the same value always gives the same token."""
mac = hmac.new(KEY, value.encode(), hashlib.sha256).hexdigest()[:8]
return f"<{kind}:{mac}>"
def clean(text):
def substitute(kind, rx, check=None):
def f(m):
v = m.group(0)
if check and not check(v):
return v # looks like an IBAN but is not: leave it alone
return pseudonym(v, kind)
return lambda t: rx.sub(f, t)
for step in (substitute("EMAIL", EMAIL), substitute("IBAN", IBAN, iban_valid), substitute("CF", CF)):
text = step(text)
return text
T = ("The customer mario.rossi@example.com (tax code RSSMRA80A01H501U) asks to change "
"the IBAN to IT60X0542811101000000123456. Reply to mario.rossi@example.com. "
"Order code AB12CD34EF567890 is not an IBAN.")
print(clean(T))
print("\ntest IBAN valid:", iban_valid("IT60X0542811101000000123456"))
print("same IBAN, last digit changed:", iban_valid("IT60X0542811101000000123457"))
# Why the key is needed: a hash WITHOUT a key of a predictable value is reversed by trying.
candidates = ["anna.verdi@example.com", "mario.rossi@example.com", "luca.neri@example.com"]
without_key = hashlib.sha256(b"mario.rossi@example.com").hexdigest()
found = [c for c in candidates if hashlib.sha256(c.encode()).hexdigest() == without_key]
print("\nhash without key reversed by guessing:", found)
with_key = hmac.new(KEY, b"mario.rossi@example.com", hashlib.sha256).hexdigest()
found = [c for c in candidates if hashlib.sha256(c.encode()).hexdigest() == with_key]
print("hash with key reversed without the key:", found)
# Output:
# The customer <EMAIL:0feaa763> (tax code <CF:d87823e0>) asks to change the IBAN to <IBAN:8337504a>. Reply to <EMAIL:0feaa763>. Order code AB12CD34EF567890 is not an IBAN.
#
# test IBAN valid: True
# same IBAN, last digit changed: False
#
# hash without key reversed by guessing: ['mario.rossi@example.com']
# hash with key reversed without the key: []
The output shows three things. The address repeated twice produces the same token, so consistency is preserved; the valid IBAN is replaced, while the order code, which passes the form but not the mod 97 check, stays intact. The last part explains why the key is indispensable: a hash without a key of a predictable value, like an email address, is reversed by trying the candidates, and trying a list of addresses is a trivial operation for a computer; with the HMAC, without the key the attempt fails. The key must live outside the repository and outside the system that writes the logs, because it is the "additional information" that Article 4 wants kept separately.
The main limit is that regular expressions find only data with a form. Names, addresses and indirect references ("the head of department who brought the lawsuit") require other techniques, and no program of a few lines replaces them. The result is a measure that reduces exposure for the categories with structure, and it must be accompanied by the simplest rule: do not write the text, if the fingerprint is enough.
Really erasing: the original is not enough
Article 17 gives the data subject the right to obtain erasure without undue delay in certain cases, including when the data are no longer necessary for the purposes or the data subject withdraws consent, and it provides for exceptions, for example for a legal obligation or for the establishment, exercise or defence of legal claims. For a system with an index and a cache, the technical point is that the data exist in several derived forms: deleting the original file leaves its passages in the index and the answers that used them in the cache.
The program below models five in-memory stores with invented data: documents, index, cache, audit log and backup. Each cache entry remembers the subjects involved, and the erasure of a subject walks through documents, index and cache. The log keeps only fingerprints, so it contains nothing to erase; the backup, instead, stays until it expires.
"""Erasure must reach the DERIVED data, not just the original.
A support system with documents, retrieval index, answer cache,
audit log and backup. Invented data, in-memory structures.
"""
import hashlib
from dataclasses import dataclass, field
def fingerprint(text):
return hashlib.sha256(text.encode()).hexdigest()[:8]
@dataclass
class System:
documents: dict = field(default_factory=dict) # id -> (subject, text)
index: dict = field(default_factory=dict) # passage id -> (subject, text)
cache: dict = field(default_factory=dict) # question fingerprint -> (passage ids, answer, subjects involved)
audit: list = field(default_factory=list) # fingerprints only, never the text
backup: dict = field(default_factory=dict) # snapshot with an expiry date
def load(self, doc_id, subject, text):
self.documents[doc_id] = (subject, text)
self.index[doc_id + "#0"] = (subject, text)
def answer(self, question, passages):
subjects = {self.index[p][0] for p in passages}
self.cache[fingerprint(question)] = (tuple(passages), "answer built with " + ", ".join(passages), subjects)
self.audit.append(("question", fingerprint(question)))
def make_backup(self, days):
self.backup = {"documents": dict(self.documents), "expires_in_days": days}
def erase_subject(self, subject):
self.documents = {k: v for k, v in self.documents.items() if v[0] != subject}
removed = {k for k, v in self.index.items() if v[0] == subject}
self.index = {k: v for k, v in self.index.items() if k not in removed}
# cached answers built with those passages must disappear
self.cache = {k: v for k, v in self.cache.items() if not (set(v[0]) & removed)}
return len(removed)
def traces(self, subject):
return {
"documents": sum(1 for v in self.documents.values() if v[0] == subject),
"index": sum(1 for v in self.index.values() if v[0] == subject),
"cache": sum(1 for v in self.cache.values() if subject in v[2]),
"backup": sum(1 for v in self.backup.get("documents", {}).values() if v[0] == subject),
}
s = System()
s.load("D1", "customer-17", "Contract of Mario Rossi, address and IBAN")
s.load("D2", "customer-18", "Contract of Anna Verdi")
s.answer("What is the IBAN of customer 17?", ["D1#0"])
s.answer("What does contract 18 provide for?", ["D2#0"])
s.make_backup(days=30)
print("before :", s.traces("customer-17"))
print("removed from the index:", s.erase_subject("customer-17"))
print("after :", s.traces("customer-17"))
print("audit log (fingerprints only):", s.audit)
print("the backup expires in", s.backup["expires_in_days"], "days")
# Output:
# before : {'documents': 1, 'index': 1, 'cache': 1, 'backup': 1}
# removed from the index: 1
# after : {'documents': 0, 'index': 0, 'cache': 0, 'backup': 1}
# audit log (fingerprints only): [('question', '62ad84bd'), ('question', '90e72a71')]
# the backup expires in 30 days
Before the erasure the subject appears in all four stores; afterwards, it remains only in the backup, which expires in 30 days. The question of whether a person can be erased from the copies immediately, or whether it is enough not to restore them and let them expire, has an answer that depends on the case and on the indications of the supervisory authority, which I have not verified here: it must be decided with your adviser and written in the procedure. Two points remain on the design side: the log that contains no text has already solved its part, and a cache with a short expiry reduces the number of entries to search. The article on backup and restore deals with the part about copies, and the one on the audit log with the one about the log.
Where the data is: residency and transfers
Keeping data on a server in Europe simplifies one point, the transfer to a third country, but does not shelter it from everything. Chapter V of the regulation deals with transfers: Article 44 establishes that a transfer takes place only if the controller and processor comply with the conditions of the chapter; Article 45 allows it if the Commission has decided that the third country ensures an adequate level of protection; Article 46, in the absence of a decision, allows it with appropriate safeguards, including standard data protection clauses adopted by the Commission. If you send data to a provider established outside the Union, or to a European provider that uses a processor or staff in a third country, Chapter V comes into play.
For the United States there is an adequacy decision: Commission Implementing Decision (EU) 2023/1795 of 10 July 2023, whose Article 1 establishes that the United States ensures an adequate level of protection for personal data transferred from the Union to organisations in the United States that are included in the Data Privacy Framework List maintained by the U.S. Department of Commerce. The General Court, with its judgment of 3 September 2025 in Case T-553/23 (Latombe v Commission), dismissed the action against that decision. An appeal against the judgment was brought on 31 October 2025 (Case C-703/25 P, notice published in the Official Journal on 22 December 2025). I have not verified the outcome of the appeal or any later developments: before relying on the decision, check its current status. A prudent company keeps a documented alternative ready, for example standard clauses.
There is also a second aspect that residency does not solve: who can compel the provider. The US rule 18 U.S.C. § 2713 says that a provider of electronic communication service or remote computing service must comply with the obligations of the chapter to preserve, backup, or disclose the contents of a communication and any record or other information pertaining to a customer within its possession, custody, or control, "regardless of whether such communication, record, or other information is located within or outside of the United States". What this means for a European provider depends on its corporate ties with entities subject to US jurisdiction, and I have no source that establishes it for any provider in particular. The practical question is this: who owns and controls the company that hosts my data? You find the answer in the contract and in the companies register, not in a "European cloud" label. The topic returns in the article on the cases in which the European cloud is worth it.
If you train or fine-tune a model with personal data, the question changes nature, because data can leave traces in the weights. The European Data Protection Board published on 18 December 2024 Opinion 28/2024 on certain data protection aspects related to the processing of personal data in the context of AI models; I do not report its conclusions because I have not read its text, and I refer you to the document. In this series we limit ourselves to the most common case, retrieval of documents with a model that does not change, described in the article on hybrid retrieval.
What hosting it yourself does not solve
Keeping the server in-house removes none of the obligations above: it assigns you all the security tasks of Article 32, from encryption to restore, which a managed provider does in your place. The article on the server in production shows that a port left open is the most concrete risk, and the one on costs that administration work weighs more than the fee. The trade-off is honest: you gain control over where the data is and who sees it, and you take on the responsibility for everything else.
Frequently asked questions
Is a server in Europe enough to comply with the GDPR?
No. Residency concerns Chapter V on transfers; the legal basis, minimization, retention, security and contracts with whoever processes data for you remain. Even a European provider may have ties with non-European entities, to be checked.
Is pseudonymized data anonymous data?
No. According to recital 26, pseudonymised data, attributable to a person with additional information, remain information on an identifiable natural person. Pseudonymization is a security measure, not an exit from the regulation.
Do I need an impact assessment for an internal assistant?
It depends on the processing. Article 35 requires it in case of high risk and lists three cases, including processing on a large scale of special categories of data. For an assistant on health or personnel data it is advisable to assess it with the data protection officer.
What you can do now
You can inventory the points where a system with a model copies personal data and decide, for each, whether to write, reduce or let expire. You can cite the articles of the regulation that weigh, you know that pseudonymization does not make data anonymous and you know why a key is needed. You know that erasing a subject means walking through index and cache, not just the original, and you know which fundamental questions remain to be asked of a provider, including who controls it. For decisions on the merits, in particular on transfers, you need your adviser: here you have the tools to ask the right questions.
The same series also includes the comparison of model families, how to measure the quality of a RAG, sizing for more users and the recap with the decision sheet.
Sources
- Regulation (EU) 2016/679 (GDPR), text on EUR-Lex - Articles 4 (pseudonymisation), 5, 17, 25, 28, 32, 35, 44, 45, 46 and recital 26, consulted on 2026-11-13
- Commission Implementing Decision (EU) 2023/1795 on the adequate level of protection of personal data under the EU-US Data Privacy Framework - Article 1 and Article 3 on continuous monitoring, consulted on 2026-11-13
- General Court of the European Union, judgment of 3 September 2025, Case T-553/23, Latombe v Commission - operative part: action dismissed, consulted on 2026-11-13
- Case C-703/25 P, appeal brought on 31 October 2025 by Philippe Latombe (notice in OJ C/2025/6610) - existence and date of the appeal; the outcome was not verified, consulted on 2026-11-13
- 18 U.S. Code § 2713, text (Legal Information Institute, Cornell Law School) - preservation and disclosure obligation independent of the location of the data; copy of the United States Code on a university site, consulted on 2026-11-13
- EDPB, Opinion 28/2024 on certain data protection aspects related to the processing of personal data in the context of AI models - existence and date of the opinion (18 December 2024); the text was not read, consulted on 2026-11-13
The two programs were run with Python 3.14.4 (python3 -I), twice, with identical output; the data is invented and the structures are in memory, with no database or network. No legal judgment is expressed: the rules are reported from the text, and the points not verified are declared in the text.

Commenti
Caricamento commenti...
Sign in to comment