Privacy model
OngoingAI Gateway treats privacy as a storage and observability concern. It forwards provider traffic while limiting what is persisted in traces.
Choose this model when
- You need model usage, latency, and cost data for operations.
- You need controls for sensitive content in AI payloads.
- You need predictable privacy-risk controls in shared deployments.
- You need enough metadata for incident debugging without default body storage.
Privacy model summary
- The gateway proxies requests to providers.
- Sensitive auth headers are redacted before trace persistence.
- Request and response bodies are not stored unless you enable body capture.
- If body capture is enabled, storage redaction is the effective default.
- Trace metadata is written asynchronously so proxy traffic is not blocked by trace storage.
Credential boundaries
- Provider credentials pass through to upstream providers for request handling.
- Provider credential values are redacted in stored trace headers.
- Gateway key headers are used for gateway auth and stripped before upstream forwarding.
What data is persisted
| Data type | Default behavior | Notes |
|---|---|---|
| Request and response bodies | Not stored | Controlled by tracing.capture_bodies. |
| Sensitive auth headers | Redacted | authorization, x-api-key, x-ongoingai-gateway-key, cookie, set-cookie. |
| Provider key identity | Stored as hash | api_key_hash is stored; last 4 chars are added to metadata when present. |
| Usage and performance metadata | Stored | Includes model, token counts, latency, TTFT, provider, status code, and path. |
| Tenant and gateway key attribution | Stored when available | Includes org_id, workspace_id, gateway_key_id, and role metadata. |
How redaction works
- Body-capture middleware records headers and optional body copies with a max
size cap (
tracing.body_max_size). - Header redaction always applies to sensitive credential headers.
- If
tracing.capture_bodies=false, request and response bodies are not persisted. - If
tracing.capture_bodies=trueand mode isredact_storage, the gateway redacts the captured body copy before persistence. - Trace metadata records redaction details such as
redaction_mode,redaction_applied,redaction_counts, andredaction_truncated.
PII mode behavior
off: Body content is stored as captured when body capture is enabled.redact_storage: Body content is redacted before storage. Upstream forwarding remains unchanged.redact_upstream: Request body content is redacted before provider forwarding on proxied provider routes.block: Request is denied when configured detectors find protected content.
Stage and detector controls
pii.stages.request_bodyandpii.stages.response_bodycontrol which body sides are redacted.pii.stages.request_headersandpii.stages.response_headerscontrol whether custom header denylist entries are applied.pii.detectorscontrols pattern detectors such as email, phone, SSN, and token-like values.pii.body.key_denylistredacts JSON fields by key name.pii.replacement.formatandpii.replacement.hash_saltcontrol placeholder format and hashing inputs.pii.scopes[]applies scoped overrides by org/workspace/key/provider/route. The most specific matching scope is selected.
Failure behavior
- In
redact_storagemode, if body redaction fails, the gateway drops body persistence for that trace and continues proxy traffic. - In
redact_upstreamandblock, the gateway fails closed if policy evaluation cannot complete on the request body, returning503. - In
block, if detection succeeds and protected content is found, the request is denied with403. - When body capture is truncated by size limit, metadata includes
redaction_truncated=truewhen redaction is active. - If configuration is invalid, startup fails fast during
ongoingai serveorongoingai config validate.
Concrete example
Given this captured request body:
JSON
{"email":"alex@example.com","api_key":"sk_test_1234567890"}With body capture enabled and pii.mode=redact_storage, stored content becomes
placeholder values:
JSON
{"email":"[EMAIL_REDACTED:...]","api_key":"[FIELD_REDACTED:...]"}The trace metadata also records redaction context:
redaction_mode: redact_storageredaction_applied: trueredaction_counts: {...}