Systemics
← All blog posts & case studies
Case Study | Compliance |

Reference Architecture — Priivy: A Rust PII detection engine that replaces Presidio at 66x to 1,525x the speed

A Rust PII detection engine that replaces Presidio at 66x to 1,525x the speed

Priivy architecture overview

What it is

Priivy is a PII detection and anonymization engine I wrote in Rust as a full replacement for Microsoft Presidio. It detects 236 entity types across more than 20 countries, validates structured identifiers with checksums (Luhn, mod-97, Verhoeff) for near-zero false positives, and anonymizes with replace, redact, mask, hash, or reversible AES-256-GCM encryption. The API is Presidio-compatible over REST and gRPC, and PyO3 bindings make it a drop-in for Python callers.

The workspace is 15 crates, one per bounded context: core types, analyzer, anonymizer, regex, NLP, server, config, CLI, structured data via Arrow, image OCR, and WASM.

Priivy Guard, the browser extension, runs the same engine compiled to WebAssembly entirely in-browser, so no PII leaves the machine for scanning. It intercepts form submits, file uploads, and fetch/XHR/WebSocket bodies, then blocks or nudges based on policy before data is sent.

Why it matters

PII scanning sits in the request path of everything: LLM gateways, upload forms, batch jobs. Presidio's Python + spaCy latency makes inline scanning expensive. Measured on identical inputs, warm cache, release build:

WorkloadPresidioPriivySpeedup
Short text (SSN)3.05 ms2.0 us1,525x
Multi-PII (5 types)5.98 ms62 us96x
10 KB document266 ms~4 ms66x
50 KB document1.59 s~14 ms114x
100 KB document3.76 s~28 ms134x

That is 66x at 10 KB and 1,525x on short texts. At these latencies (124 us for the full analyze plus anonymize pipeline), DLP stops being a batch job and becomes an inline filter. The workspace runs about 675 tests.

Architecture decisions

Regex-first, ML optional. The regex-only build compiles to under 5 MB with zero ML dependencies; ONNX models (GLiNER for zero-shot NER, Piiranha for fixed-vocabulary PII) sit behind feature flags for when recall on unstructured names matters, and both can run together through a composite engine. Feature flags keep the minimal Docker image around 15 MB while the full model images run 500-600 MB.

Parallelism by construction. Documents split into overlapping 4 KB chunks processed by rayon, recognizers fan out concurrently within each chunk, and results merge with offset correction and deduplication across overlap zones. Zero-copy text slices and static entity names keep heap allocation out of hot paths; the regex crate's SIMD literal matching does the rest.

Strict lints as policy: no unsafe, no unwrap, expect, or panic, no unchecked indexing, enforced workspace-wide. Encryption-based anonymization is reversible by design, but deanonymize requires an Operator+ role and is audit-logged before decryption runs, with metadata only (text length, entity types, outcome), never content. The extension is WASM rather than a cloud call, because scanning PII by sending it to a server fails the pitch. Production deploys through a Helm chart with Envoy Gateway, Vault secrets, and PostgreSQL 18.


Book a free assessment: systemics.ai.

Start with a free architecture assessment.

Thirty minutes, no slides. Tell us where your AI posture stands and we will tell you honestly whether we can help.