Skip to main content
PromptGuard runs detectors in three tiers: a fast path of in-process regex and heuristic checks that covers roughly 95% of traffic in single-digit milliseconds, an ML path that calls hosted classifier models, and a slow path of LLM-judge detectors that are opt-in and bounded by hard timeouts. This page gives a realistic p99 budget for each detector so you can reason about the tail.

The overall target

The number reported as processing_time_ms on each event (see the Analytics Cookbook) is engine-only time — it excludes the upstream provider call on the proxy path. The design goal is that the common case stays on the fast path. ML and LLM detectors only run when a project enables them, when the fast path is ambiguous, or when a plan tier unlocks them — so the tail is opt-in, not paid on every request.

What we have actually measured

The budgets above are targets. The most recent full benchmark run — 5,384 samples, ml_enabled, default:moderate preset — measured:
Read that as a worst-case profile, not a typical one. Benchmark corpora are adversarial by construction, so nearly every sample is ambiguous enough to escalate past the fast path into ML. Application traffic is mostly benign and short-circuits far more often — runs of the same harness where inputs never reached the ML service came back at 0.13–0.17 ms mean, four orders of magnitude apart.That spread is the real point: your latency is dominated by how often you escalate, not by any single headline number. Measure your own traffic rather than adopting either figure.

Fast path — deterministic detectors

These run in-process on every eligible request, in the order below (the engine short-circuits and returns as soon as a blocking detector fires). No network calls, so latency is CPU-bound and scales with input length. Fast-path total p99: a few milliseconds for typical prompt sizes. Very large inputs (long documents, tool outputs) push the regex and PII stages higher — budget generously if you scan multi-KB payloads.

ML path — hosted classifier models

When ML_INFERENCE_MODE=api, injection, toxicity, and NER-based PII delegate to hosted transformer models. Latency is dominated by the network round-trip and possible model cold-start, not local compute.
The ML path fails open to regex. If the inference API times out, cold-starts, or is unreachable, the request still gets the deterministic verdict — you lose recall, not availability. Flip ML_INFERENCE_MODE=off to force regex-only (used for emergency cost/latency cutting). Self-hosted deployments can point DETECTION_ML_BASE_URL at a local TGI/vLLM endpoint to keep this path in-network.

Slow path — LLM-judge detectors

These call a generative LLM to reason about context. Each is opt-in per project or plan tier and guarded by a hard timeout; on timeout the detector falls open and the request proceeds on the fast/ML verdict. Treat the timeout as the p99 ceiling — the budget is “as fast as the model answers, never longer than this.”
A non-instruct reasoning model on the LLM-guard slow path can blow the budget: it spends the token allowance “thinking” and gets truncated before emitting the verdict JSON, which then fails open. The default (Qwen2.5-7B-Instruct) is a non-thinking instruct model chosen precisely to answer within the 8 s budget. If you override LLM_GUARD_MODEL, pick an instruct model.

Keeping the tail small

  • Lean on the cache. Identical inputs reuse the prior verdict in < 0.1 ms. High cache-hit rates are the single biggest lever on p99.
  • Only enable the slow path where it earns its keep. LLM-judge detectors are for ambiguous, high-stakes surfaces (agentic tool calls, custom NL policies, RAG grounding) — not every endpoint.
  • Right-size ML_INFERENCE_MODE. api for recall, off for the lowest, most predictable latency, a local DETECTION_ML_BASE_URL for in-network ML.
  • Set fail_mode deliberately. open favors availability (allow on engine error); closed favors safety (block on error). Zero-trust projects should run closed and accept that a slow/unreachable detector then blocks rather than falls open.
  • Measure, don’t guess. These are budgets. Read your actual percentiles from the promptguard.detector.latency OTEL histogram or the Analytics Cookbook. Per-detector timings are also emitted in each event’s event_metadata.

Measuring it yourself

The budgets above are engine-only. What your users feel is engine time plus the network hop to PromptGuard, so measure from the client to get the number that matters to them:
Two things that will otherwise confuse the result. Warm the cache first — identical inputs reuse the prior verdict in under 0.1 ms, so a loop over one string measures your cache, not your detectors. Vary the input to measure the real path. And run this from where your app runs: from a laptop you are largely measuring your own internet connection, not PromptGuard.
To compare against the engine-only budgets in the tables above, query processing_time_ms from your event telemetry instead — that field excludes both the network hop and any upstream provider call. The Analytics Cookbook has the SQL.

Next steps

Analytics Cookbook

Measure your real p50/p95/p99 by detector and surface

Threat Detection

What each detector catches

Reliability

Fail-open vs fail-closed and graceful degradation

Rate Limits

Throughput and quota behavior