Implementation guide
PII Redaction
PII redaction is how you stop personally identifiable information from reaching models, logs, vector stores, and citations. This guide explains what it is, where it belongs in AI pipelines, and how to implement it locally in Node.js before prompts ever leave your process.
What is PII redaction?
PII redaction is the practice of detecting and masking information that can directly or indirectly identify an individual before that data is stored, processed, or exposed downstream. In AI systems, that includes prompts, model outputs, logs, traces, embeddings, analytics, and any citation that points back to user data.
Unlike a one-off filter, effective PII redaction is a control plane: the same entity taxonomy and masking policy applied at every trust boundary so a single prompt cannot fan out into vendor APIs, RAG indexes, and observability tools unchanged.
PII broadly covers two categories:
- Direct identifiers: email addresses, phone numbers, names, national IDs, account numbers
- Indirect or quasi-identifiers: dates of birth, postcodes, job titles, and combinations of attributes that re-identify a person when linked
What matters most is not only what counts as PII, but where it can appear. For detection primitives and pattern coverage, see the PII detection overview.
Why PII redaction matters
AI systems amplify traditional privacy risks because they copy, transform, and log data across multiple layers. Without redaction, a single prompt can end up in model vendor logs, vector stores, observability platforms, and audit trails.
Common injection points
- Inbound streams: user prompts, uploads, and pasted exports (CSV, DOCX, CRM snapshots)
- Processing layers: system logs, traces, APM instrumentation, and replay tools
- Storage: vector databases, embeddings, RAG indexes, and training sets
- Outbound channels: model responses that echo prompts, retrieved snippets, or internal context
- Regulatory compliance: GDPR, CCPA, HIPAA, and sector rules expect proactive controls on personal data (see GDPR redaction and HIPAA redaction)
- Security posture: masking high-value identifiers reduces the blast radius of any breach
- Trust and adoption: users and customers adopt AI features faster when privacy controls are concrete and inspectable
Core PII entities and redaction targets
Start with clear entity definitions and a consistent masking strategy per entity. In AI pipelines, the same entities show up in prompts, tool outputs, RAG documents, citations, logs, traces, and embeddings.
Contact information
Emails, phone numbers, postal addresses, postcodes
Identity numbers
National IDs, SSNs, passport numbers, driver’s licenses, NHS/NINO-style identifiers
Financial data
Credit cards, IBANs, account numbers, routing / sort codes
Health identifiers
Patient IDs, clinical record IDs, insurance member IDs (HIPAA-bound systems)
Online / device identifiers
IP addresses, device IDs, cookies where regulations treat them as personal data
Free-text personal details
Names, employers, locations, and attribute combinations that can re-identify someone
Ask for your use case: which of these entity types is most likely to appear in logs or citations? Start there, then expand coverage once recall and false-positive rates are measured.
Redaction vs anonymization vs tokenization
Different privacy techniques serve different goals. Mixing them up leads to brittle designs.
| Technique | What it does | Best for |
|---|---|---|
| Redaction | Remove or mask the sensitive value (e.g. [EMAIL_9619]) | Prompts, logs, model traffic when structure/context remains useful |
| Anonymization | Transform so individuals are no longer identifiable, even when linked | Long-term analytics, public datasets, aggregated reporting |
| Tokenization | Replace values with reversible tokens plus a secure map | Internal workflows that still need authorised re-identification |
For AI citations, redaction and tokenization matter most: citations should not leak real identifiers, but privileged services may still need to resolve a placeholder back to a record.
Pattern-first vs machine learning detection
There are two dominant paradigms for detecting sensitive text: pattern-first (regex-based) and ML/NLP-based. Production systems usually combine both—starting with the layer you can deploy everywhere without shipping raw text to another processor.
Pattern-first (regex / rule-based)
Regex-driven detectors catch structured identifiers—emails, phone numbers, credit cards, postal codes, and national IDs— with deterministic precision. They are fast, local, and auditable, which makes them the right first hop before content reaches an LLM API.
ML / named entity recognition (NER)
NER expands coverage to unstructured narrative—names, organisations, and contextual references that rigid patterns miss. Trade-offs are latency, cost, and data residency if inference runs outside your boundary.
Optimal architecture: run high-precision pattern redaction locally, optionally apply NER inside a private VPC, then merge spans in a single pass. OpenRedaction focuses on the deterministic layer you can ship in every Node process; optional local NER sits behind the same boundary when you need free-text name coverage.
Defense-in-depth: a multi-layer strategy
Modern AI systems need PII controls at multiple layers, not a single filter at the edge.
- Input layer: redact or tokenise before data reaches the model or vector store
- Logging layer: scrub structured logs, traces, and metrics (including OpenTelemetry attributes)
- Storage and analytics: anonymize or aggregate before long-term retention
- Output and citations: ensure responses, explanations, and provenance never re-emit raw identifiers
Keep a shared entity taxonomy and redaction policy across layers so one hop does not undo another.
How to implement PII redaction with OpenRedaction
OpenRedaction is a regex-first, open-source library that detects and redacts PII locally in Node.js. Use it as the deterministic control plane before LLM calls, RAG indexing, and log export. The steps below mirror the pattern used in production AI agent stacks: install a specialized redactor, wrap sensitive payloads, then keep observability tools from storing the originals.
Step 1: Install the library
npm install openredactionStep 2: Detect and redact a string
detect() is async and returns the redacted text plus a redactionMap for authorised restore flows.
import { OpenRedaction } from "openredaction";
const redactor = new OpenRedaction({
preset: "gdpr",
redactionMode: "placeholder",
deterministic: true,
});
const input =
"Hi, I'm Jane Smith. Email jane@acme.com or call 07700900123.";
const result = await redactor.detect(input);
console.log(result.redacted);
// e.g. "Hi, I'm [NAME_...]. Email [EMAIL_...] or call [PHONE_UK_MOBILE_...]."
console.log(result.detections.map((d) => d.type));
// ["NAME", "EMAIL", "PHONE_UK_MOBILE"]Step 3: Redact before an LLM API call
Never pass raw user text to a third-party model when PII is possible. Full walkthrough: redact PII before OpenAI.
import OpenAI from "openai";
import { OpenRedaction } from "openredaction";
const client = new OpenAI();
const redactor = new OpenRedaction({ redactionMode: "placeholder" });
async function safeCompletion(userPrompt: string) {
const { redacted } = await redactor.detect(userPrompt);
return client.chat.completions.create({
model: "gpt-4.1-mini",
messages: [{ role: "user", content: redacted }],
});
}Step 4: Scrub request bodies with Express middleware
Put redaction at the gateway so every route inherits the same policy. See also the Node.js redaction guide.
import express from "express";
import { openredactionMiddleware } from "@openredaction/express";
const app = express();
app.use(express.json());
app.use(
openredactionMiddleware({
autoRedact: true,
fields: ["prompt", "message", "content"],
}),
);
app.post("/chat", (req, res) => {
// req.body fields are already redacted
res.json({ ok: true, body: req.body, pii: req.pii });
});Step 5: Keep session-scoped maps for citations (optional)
Stable placeholders keep RAG citations readable. Store redactionMap only in an authorised, short-lived context—never in the vector store or public citation payload.
const redactor = new OpenRedaction({
redactionMode: "placeholder",
deterministic: true,
});
async function prepareChunkForIndex(chunk: string) {
const { redacted, redactionMap } = await redactor.detect(chunk);
// Persist only redacted text in your vector DB / citation index
await indexDocument({ text: redacted });
// Keep the map in a privileged session store if restore is required
await sessionStore.set(sessionId, redactionMap);
return redacted;
}
// Later, privileged internal tooling only:
const map = await sessionStore.get(sessionId);
const restored = redactor.restore(redactedCitation, map);Before / after
Contact jane@acme.com about order #4412, SSN 078-05-1120Contact [EMAIL_…] about order #4412, SSN [SSN_…]Where to redact in AI pipelines
Placement is as important as detection quality. Treat every hop where text leaves a trust boundary as a redaction checkpoint.
- Before inference (gateway): scrub inputs and tool results before third-party LLMs
- Application / RAG layer: redact early in chunking so embeddings never store raw identifiers
- Observability layer: use collectors and span processors to scrub attributes before export
- Response path: scan generated replies before storage or display—models can echo user inputs or retrieved snippets
- Storage and analytics: tokenize or aggregate before dashboards and training sets
In practice, many teams combine a model gateway with collector-level redaction for logs and traces.
Redaction styles and consistency
How you represent scrubbed values matters as much as catching them. Pick a style, document it, and apply it globally—auditors prefer a stable schema over clever one-offs.
- Full placeholders (e.g.
[EMAIL_9619]) for external model traffic and vendor APIs - Partial masking (e.g.
jo***@domain.com) only for internal dashboards or controlled analytics - Token replace when a privileged service must restore the original later
OpenRedaction supports placeholder, mask-middle, mask-all, format-preserving, and token-replace modes so you can use irreversible placeholders for vendors and softer masking for internal tools.
Redaction in logs, traces, and telemetry
Most compliance findings involving AI stacks come from logs and observability data—not just primary databases.
- Prefer field-level redaction in structured logs before serialisation
- Scrub span attributes and events that may contain emails, tokens, or prompt bodies
- Ensure debug logs and stack traces never dump raw prompts
- Separate operational logs from compliance audit logs—neither should retain raw identifiers by default
You can also apply collector-level masking (useful when many services need a central policy). Example OpenTelemetry Collector snippet:
processors:
attributes/pii:
actions:
- key: user.email
action: delete
- key: http.url
regex: '(\?|&)(token|password)=([^&]+)'
action: update
value: '[REDACTED]'
service:
pipelines:
traces:
processors: [attributes/pii]Collector rules catch known attribute keys. Application-layer OpenRedaction still matters for free-text prompts and message bodies those keys will not cover.
Designing redaction for AI citations
AI citations refer model outputs back to source documents, prompts, or intermediate artifacts. If those sources contain PII, citations become a leak point even when the answer looks safe.
- Stable placeholders: replace PII with consistent tokens (
[PERSON_1],[EMAIL_1]) so citations remain meaningful - Session-scoped redaction maps: only privileged services can de-redact
- Redacted metadata: titles, IDs, and document labels must not encode PII
- Constraint-based outputs: prevent the model from reconstructing raw identifiers from context
Policies, classification, and governance
Effective PII redaction is driven by policy, not only tooling.
- Classify data tiers (public, internal, sensitive, regulated)
- Map entity types to regulations (for example, SSN → GDPR / HIPAA expectations)
- Define who can see de-tokenised data versus fully masked outputs
- Treat redaction configuration as code—versioned, reviewed, and approved
OpenRedaction presets (gdpr, hipaa, ccpa, finance, education, healthcare) give teams a concrete starting policy they can inspect and override.
Evaluation: precision, recall, and quality
Privacy assurance is not theoretical—it needs continuous, automated proof. Treat redaction checks as part of CI/CD, not a post-incident cleanup.
- Maintain fixture sets with known PII and assert nothing sensitive reaches models or logs
- Inject canary values (e.g. a unique test email) into prompts and verify they never appear in logs, embeddings, or LLM responses
- Prioritise recall for high-risk entities even when that means some over-redaction
- Track latency budgets (for example under 50ms per prompt)—if redaction slows the path, teams will bypass it under pressure
- Periodically scan vector stores and citation indexes for regressions
No automated system catches everything. Keep review queues for low-confidence matches, especially in healthcare, legal, and HR workflows—see also PII in support tickets.
Where OpenRedaction fits in
OpenRedaction provides an open-source foundation for detecting and redacting a broad set of PII entities using extensive regex libraries, validators, and configurable masking modes. Pair it with optional NER, structured logging, and clear policies for end-to-end coverage.
- Gateways in front of LLMs
- Middleware scrubbing for APIs and support tools
- Pre-processing documents and prompts before RAG or search indexes
- Local, auditable redaction for compliance reviews
Compare approaches on open source AI redaction tools, or read how the library was built in Building OpenRedaction.