FlowKit

Anonymizing personal data before sending it to an LLM with n8n (GDPR)

Published 4 August 2026 · 6 min read

Your n8n workflows are already sending customer data to an LLM: a full email goes to OpenAI to be classified and prioritized, a support ticket goes to Anthropic to be scored, a complaint file gets summarized. In each of these cases, the customer's name, email, sometimes their phone number or address travels to a third party — even though the model often only needs the content of the message to do its job. This is exactly the kind of processing that Article 5.1.c of GDPR targets with the data minimization principle: only collect and transmit what is adequate, relevant, and limited to what is necessary.

This guide shows how to build, inside n8n, an anonymization or pseudonymization layer between your data and the LLM call — without breaking the business logic that often needs the real data afterward.

Why the provider's DPA isn't enough on its own

Signing a Data Processing Addendum with OpenAI or Anthropic covers the contractual framework of the transfer: legal basis, security commitments, what happens to the data upon termination. But a DPA doesn't exempt you from minimization upstream. Two concrete reasons to act before sending rather than relying solely on the provider's contract:

  1. The burden of proof of compliance is on you. In case of an audit, demonstrating that your workflows only expose the strict minimum is stronger evidence than a signed DPA that was never actually enforced in the automation's code.
  2. The risk of memorization by the model isn't zero. Researchers from Google and other institutions, Carlini et al. (2021), demonstrated that it is possible to extract memorized training data sequences from large language models, including personal information (see the study on Google Scholar). That result concerns training, not inference via API — but it illustrates why limiting personal data exposure remains good practice even with a serious provider: the less a piece of data circulates, the fewer surfaces it has to leak through.

Two strategies, for two different needs

Not everything is handled the same way depending on whether you need to recover the real data after the AI call, or not.

Irreversible masking: when the real data isn't needed again

For a strictly analytical use — aggregated statistics, trend detection in customer feedback, an anonymous summary report — replacing identifiers with generic text is enough and simplifies everything: no table to manage, no risk of leaking back the other way. This is exactly what n8n's Guardrails node does with its Sanitize Text operation: without calling an LLM, through simple pattern matching, it detects and replaces emails, phone numbers, credit card numbers, and other standard PII with generic tokens ([EMAIL_ADDRESS], [PHONE_NUMBER]…).

Reversible pseudonymization: when you need to reply to the right customer

The most common case for an SMB is different: you want the AI to classify, summarize, or prioritize a ticket without seeing the customer's identity — but your workflow then needs to know who to reply to. This is where reversible pseudonymization comes in: each identifier is replaced with an opaque token before the LLM call, and an encrypted mapping table lets you get back to the real value once the model's response is obtained.

Building reversible pseudonymization in n8n

The mapping table in Supabase

Create a dedicated table, separate from your business data, accessible only to the workflow that needs it:

create table pseudonymization_tokens (
  token text primary key,
  original_value text not null,
  field_type text not null,
  created_at timestamptz default now()
);

create index idx_pseudo_created on pseudonymization_tokens (created_at);

Isolating this table (dedicated schema, restricted permissions) prevents access to the business data alone from being enough to lift the anonymization — the very principle of pseudonymization under GDPR, which distinguishes it from full anonymization as long as the mapping table exists somewhere.

The Code node that replaces and records

Upstream of the LLM call, a Code node detects the identifiers (regex or, for a more thorough approach, the Guardrails node in detection-only mode), generates a unique token for each one with the Crypto node (a truncated hash is enough — what matters is uniqueness, not mathematical reversibility, since the real value lives in Supabase), then inserts the token/value pair into the table before continuing the workflow with the pseudonymized text.

const email = $input.first().json.email;
const token = `TOK_${require('crypto').createHash('sha256').update(email + Date.now()).digest('hex').slice(0, 12)}`;
return [{ json: { ...$input.first().json, email: token, _originalEmail: email } }];

The following Supabase node (Insert operation) persists the mapping; the _originalEmail field is only used by that insert node and must never be sent onward to the LLM.

The complete workflow, step by step

  1. Trigger (Webhook, IMAP, form): reception of the raw data.
  2. Code node — anonymization: PII detection, token generation, cleaned text passed to the output.
  3. Supabase node — Insert: writing the token → real value mapping.
  4. AI Agent or HTTP Request: LLM call with only the pseudonymized text — classification, summary, scoring.
  5. Supabase node — Select: reading back the mapping from the tokens present in the response.
  6. Code node — de-pseudonymization: reinserting the real values into the final result before the output action (email sent, CRM entry, Slack notification).

This pattern plugs directly into an AI email triage pipeline or a support ticket scoring pipeline: only steps 2 and 5-6 are added to the existing workflow, the core of the AI processing doesn't change.

The trap of indirect identifiers

Masking the obvious fields (name, email, phone) isn't always enough. A now-classic study by Latanya Sweeney, published in 2000, showed that in the United States, the mere combination of ZIP code, date of birth, and sex allowed unique re-identification of about 87% of the population (see the study on Google Scholar). In other words: it's not the fields with explicit names ("email", "phone") that pose the biggest long-term risk, but combinations of contextual details in free text — a city, a job title, an appointment date, a precise amount. For a support ticket or a detailed complaint, regex masking on structured fields alone doesn't cover this risk; you either need to run the free text through Guardrails PII in a broader detection mode, or accept that some free-text fields stay out of scope for automation and go through human review before any sensitive AI processing.

What about a self-hosted LLM?

Running the model locally with Ollama removes the risk of transfer to a third party: the data never leaves your infrastructure. That doesn't make pseudonymization useless, though — it also reduces exposure in your own n8n execution logs, in application logs, or to a provider administering the server. It's defense in depth, not a checkbox that only counts for external providers.

Common pitfalls

  • Pseudonymizing only structured fields while leaving free text untouched: that's often where indirect identifiers hide.
  • Storing the mapping table in the same database as business data, without permission separation: that cancels out much of the benefit of pseudonymization.
  • Forgetting to purge the token table: set a retention period consistent with the actual need (usually just the duration of processing, rarely more), the same way you would for your processing register.
  • Relying on the AI provider's DPA as the only measure: it's a contractual building block, not a substitute for technical minimization.
  • Over-engineering for a low-risk case: an aggregated internal digest doesn't need the same level of pseudonymization as an HR or health file — match the effort to the actual risk of the processing.

In summary

Sending raw personal data to a third-party LLM, even under a DPA, often goes beyond what GDPR minimization requires. Irreversible masking via the Guardrails node is enough for purely analytical uses; reversible pseudonymization with a Supabase mapping table covers cases where the workflow needs to get back to the real identity after the AI call. Both are built with nodes already present in n8n — Code, Crypto, Supabase — with no additional third-party service. The Compliance & Audit Pack (149 €) provides a ready-to-use Supabase audit trail that naturally fits alongside this kind of mapping table; for a first concrete use case to secure, the AI Inbox Pack (79 €) remains the fastest one to put to work.

FAQ

Frequently asked questions

Isn't the DPA signed with OpenAI or Anthropic enough to cover GDPR?

A Data Processing Addendum (DPA) covers the contractual side of the data transfer, but not the data minimization obligation under Article 5.1.c of GDPR: you must demonstrate that you only send the data strictly necessary for the processing. Sending a name, email, and phone number to an LLM to classify a support ticket when a pseudonymized identifier would suffice is a violation of that principle, signed DPA or not.

Does regex masking actually anonymize data properly?

No, and this is a common misconception. Regex masking removes obvious direct identifiers (email, phone, IBAN) but often misses combinations of indirect identifiers — a job title, a city, and a date can sometimes be enough to re-identify a person. For risky free text (detailed complaints, HR files), regex masking is a first layer, not a guarantee of complete anonymization.

Should you pseudonymize even when using a self-hosted LLM like Ollama?

The urgency is lower since the data no longer leaves your network, but the good practice still holds: limiting personal data exposure to the strictly necessary surface also reduces internal risks (application logs, n8n execution logs retaining payloads, access by a maintenance provider). Pseudonymization protects against more scenarios than just a transfer to a third party.

Bundle FlowKit Complet

€269