This episode turns logs into evidence: auditing route decisions and model usage, recording policy evaluations and access history, and handling data residency and privacy compliance with organized encryption and retention.

Episode 13 made the gateway tough: inputs guarded, content moderated, PII redacted, and providers protected. But you still can't prove any of that happened. When an auditor asks "whose request ever called the payment tool?", or a regulator demands "in which country is our users' model data processed?", answering "it should be safe" isn't enough.
Episode 14 turns the behavior you've built into an accountable trail. We'll enable audit logs for route decisions and model usage, record policy evaluations and access history, then discuss compliance considerations: data residency, privacy, encryption, and retention.
An audit log isn't just a regular log. Operational logs answer "what's happening now", while audit logs answer "who did what, when, through which route, and how the decision was made" with enough context for post-incident investigation. After writing the audit configuration, run 9router audit enable to activate it. 9router records important events in a structured way:
audit:
enabled: true
destination: stdout
events:
- auth_event
- route_decision
- policy_evaluation
- tool_invocation
- guardrail_trigger
- cache_hit
redact:
- authorization
- api_key
- prompt_contentNote the redact here: prompt content is intentionally not recorded unless truly needed, because data that is never stored can never leak. Every entry has a standard format so it can be consumed by a SIEM, parsed, and joined with other infra logs.
{
"ts": "2026-08-03T09:15:22Z",
"event": "route_decision",
"request_id": "req_9f2c1a",
"consumer": "mobile-app",
"region": "ap-southeast",
"route": "chat-general",
"selected_model": "gpt-4o-mini",
"provider": "openai-prod",
"tokens_in": 412,
"tokens_out": 96,
"latency_ms": 743,
"policy_version": "v42"
}Routing decisions must be explainable after the fact. Why did this request land on gpt-4o and not gpt-4o-mini? The answer is in the route_decision entry: the chosen route, model, provider, and the policy_version in effect at that time. Policy version matters because old decisions must be auditable with the same rules as when they happened.
9router audit query --event route_decision --consumer mobile-app --since 24h
9router audit show --request-id req_9f2c1aModel usage is summarized into aggregatable metrics for cost and capacity reports: total tokens per model, per provider, and per consumer. This data is also the basis for cost attribution — knowing which business unit spends the most of the AI budget.
9router audit summary --by model --window 7d
9router audit export --format csv --window 30dOne of the audit log's greatest values: proving that policies were actually evaluated on every request. The policy_evaluation entry records which policy was active, its outcome (passed, rejected, redacted), and the reason. This matters for compliance audits and also for tuning — if many requests are blocked, you know a policy is too strict.
{
"event": "policy_evaluation",
"request_id": "req_a71b9d",
"policy": "content-safety",
"guard": "pii-scrub",
"entity": "credit_card",
"action": "redact",
"result": "allowed_with_redaction"
}Likewise, guardrail_trigger records when prompt_injection or moderation-in blocked a request. A suspicious number of blocks — for example a sudden spike from one IP — is a signal that must be followed up, and thanks to the audit log, that signal has evidence.
Audit also records who accessed what. auth_event records authentication successes and failures; tool_invocation records which tool was called, by which consumer, and with what arguments. Access to the gateway admin panel and configuration changes must also enter the log — who changed a rate limit, when, and from which version to which.
audit:
access_control:
viewers: [security-team, compliance-team]
immutable: true
export_require_mfa: trueSetting immutable: true makes audit entries unable to be edited or deleted — the foundation of evidence integrity. Access to the logs is limited to specific teams, and data export requires MFA. This pattern follows the least-privilege principle from episode 11, applied to the evidence itself.
Warning
Beware retention rules: keeping logs forever can violate privacy regulations, while deleting too quickly destroys investigation capability. Set retention aligned with your policy, then automate rotation and deletion.
The awareness that "logs live on one server" is no longer enough when data crosses borders. Data residency demands that data be processed in approved regions — for example European citizens' data must stay in Europe. 9router supports region pinning: forcing specific routes to only use providers located in allowed regions.
residency:
region: eu-central
enforce: true
providers_allowed: [azure-eu]
deny_cross_border: true
audit_events: trueWith enforce: true, a request that configurationally lands on a provider outside the allowed region is rejected — not just recorded. Combine this with the ABAC rule from episode 12 (request.region != eu denied) so the residency policy applies consistently at the routing layer and the request layer.
storage:
encryption: aes-256
kms_key_ref: kms/9router-audit
retention:
audit_log: 90d
request_meta: 30d
pii_tokenization: trueEncryption at rest ensures log files and metadata remain unreadable even if the storage media is stolen. PII data that slips into metadata — if any — is tokenized so it's not in its original form. The combination of residency pinning, encryption, and automated retention is the outline of compliance you can present to the compliance team, while waiting for episode 20 to dashboard the metrics.
Episode 14 makes your gateway accountable: structured audit logs for route decisions and model usage, records of policy and guardrail evaluations proving protection is running, access history for credentials and tools, plus data residency, at-rest encryption, and retention policies aligned with privacy.
Key takeaways:
Now every decision has a trail. In episode 15 we make that trail fast and cheap: Performance Optimization — optimizing routing latency and throughput, balancing cost/latency when choosing models, and caching responses and reusing embeddings. See you there!