Bouncer performance tuning
Audience: DevOps / Platform / Security engineers
Time: ~25 min to configure and verify
Prerequisites: At least one Bouncer deployed (Bouncer deployment), controls syncing via Policy Bridge (Deployment overview)
This guide covers the settings that keep inline authorization (PEP → policy engine) in the sub-5 ms product latency envelope: local Unix-socket evaluation, Policy Bridge–preloaded attribute data, optional agentic batch checks, and memory ceilings. Use it when you need predictable P50/P99 decision latency under load.
What “fast” means in Control Core
| Target | Value |
|---|---|
| P50 decision latency | ≤ 0.8 ms at 20k requests/second |
| P99 decision latency | ≤ 4.8 ms at 100k requests/second |
| P99.9 during Policy Bridge sync bursts | ≤ 8.0 ms |
| Policy engine + Policy Bridge client memory | ≤ 256 MB per Bouncer pod (guidance) |
These apply to the allow/deny decision path (authorization filter). Response-body mutation (masking/redaction) has a separate, longer timeout and is not part of the sub-5 ms contract.
Troubleshooting: If latency spikes only when controls change, check Policy Bridge sync health in the Control Plane audit feed (
OPAL_SYNC_*/ sync history) before changing Bouncer knobs. See Troubleshooting.
1. Local evaluation transport (Unix socket) — ~5 min
By default the Bouncer evaluates controls against a co-located policy engine over a Unix domain socket inside the pod. That avoids TCP loopback overhead on every decision.
| Setting | Default | Purpose |
|---|---|---|
OPA_UDS_PATH | /var/run/opa/opa.sock | Socket path for decision evaluation |
| (fallback) | set to off or tcp | Force TCP to the policy engine (compatibility / debugging only) |
The policy engine still listens on TCP port 8181 for Policy Bridge data writes and health probes. Decision traffic should use the socket.
Verification
# Inside the Bouncer container — socket should exist and be writable by the bouncer user
ls -la /var/run/opa/opa.sock
# Confirm UDS is configured (example for Kubernetes)
kubectl exec -n <ns> deploy/<bouncer> -- printenv OPA_UDS_PATH
Expect OPA_UDS_PATH=/var/run/opa/opa.sock (or your custom path), not off.
Troubleshooting: If decisions fail open/closed unexpectedly after a restart, confirm the socket directory is mounted and owned correctly, then check Bouncer logs for transport fallback messages. Full reference: Troubleshooting.
2. Keep attribute data off the hot path — ~10 min
Do not call external attribute APIs (IdP, HR, threat intel) on every request. Attribute data should arrive through Policy Bridge into the local policy engine memory (data.pip.*). Per-request “enrichment” HTTP to the Control Plane is off by default and must stay off for production latency.
| Setting | Default | Purpose |
|---|---|---|
CC_CONTEXT_ENRICHMENT_ENABLED | false | Allows background context HTTP only when true — never use as a per-request dependency |
PIP freshness tiers (banking / defence posture)
After each decision, the Bouncer can check freshness metadata (_cc_pip_meta) for preloaded PIP documents. Stale realtime data can fail closed in strict mode.
| Setting | Default | Notes |
|---|---|---|
BOUNCER_PIP_STALENESS_MODE | warn | strict / warn / ignore |
BOUNCER_PIP_REALTIME_TTL_SEC | 30 | Max age for realtime attributes |
BOUNCER_PIP_REFERENCE_TTL_SEC | 900 | Max age for reference attributes (15 min) |
BOUNCER_PIP_SENTINEL_TTL_SEC | 3600 | Max age for sentinel / threat intel (60 min) |
CC_PIP_HMAC_KEY | unset | Tier-0 secret: verify integrity of PIP metadata when set |
BOUNCER_PIP_CLASSIFIED_ISOLATION | false | Defence posture: classified data namespace + hardened isolation |
Helm posture overlays (Custom / Kubernetes installs):
- Banking / OSFI-FINTRAC style:
values-pip-banking.yaml—strict, HMAC expected, enrichment off, UDS on - Defence / classified:
values-pip-defence.yaml— stricter realtime TTL, classified isolation, memory limit viaGOMEMLIMIT
helm upgrade --install controlcore ./controlcore \
-f values.yaml \
-f values-pip-banking.yaml
Store CC_PIP_HMAC_KEY in your secret manager (secretKeyRef / ExternalSecrets) — never plaintext in values files.
Verification
- In Control Plane → Audit, confirm Policy Bridge sync completed for the environment.
- Confirm
CC_CONTEXT_ENRICHMENT_ENABLEDis unset orfalseon Bouncer pods. - For banking/defence: confirm
BOUNCER_PIP_STALENESS_MODE=strictand HMAC secret mounted.
Troubleshooting: Unexpected denies with reason containing
PIP_STALE_*mean freshness failed closed — refresh the PIP source via Policy Bridge or temporarily set mode towarnwhile investigating. Attribute mapping help: PIP admin guide.
3. Agentic batch authorization (optional) — ~5 min
AI agents that predict several tool calls can request N decisions in one gRPC round-trip instead of N separate authorization calls. This reduces IPC overhead for agentic sequences. The API accepts generic subject / action / resource / environment tuples only — no application-specific branches in the Bouncer.
| Setting | Default | Purpose |
|---|---|---|
BOUNCER_BATCH_AUTHZ_ENABLED | false | Start the batch authorization gRPC service |
BATCH_AUTHZ_PORT | 9194 | Listen port inside the pod |
BOUNCER_BATCH_AUTHZ_MAX_TUPLES | 64 | Max decisions per request (hard cap 256) |
BOUNCER_BATCH_AUTHZ_WORKERS | 8 | Concurrent evaluators per batch |
Verification
# With the flag enabled, the Bouncer should listen on the batch port
kubectl exec -n <ns> deploy/<bouncer> -- printenv BOUNCER_BATCH_AUTHZ_ENABLED BATCH_AUTHZ_PORT
Wire your agent runtime to controlcore.batch.v1.BatchAuthz/Evaluate on that port (same network namespace as the Bouncer). Leave the flag off unless an agent platform needs it.
Troubleshooting: If batch calls time out, check network policies allow pod-local TCP to
BATCH_AUTHZ_PORT, and that tuple count ≤BOUNCER_BATCH_AUTHZ_MAX_TUPLES. Standard API traffic continues to use the Envoy authorization filter regardless of this flag.
4. Memory ceiling for the policy engine — ~5 min
There is no opa --max-memory-alloc flag. Cap memory with the Go soft limit plus Kubernetes limits:
| Setting | Example | Purpose |
|---|---|---|
GOMEMLIMIT | 256MiB | Soft memory limit for the policy engine process |
Pod resources.limits.memory | ≥ GOMEMLIMIT | Hard cgroup limit (set in Helm values) |
Defence overlay sets GOMEMLIMIT=256MiB as a starting point. Raise only with measured heap profiles — keep the pod budget near 256 MB for policy engine + Policy Bridge client unless you have an approved exception.
Verification
kubectl exec -n <ns> deploy/<bouncer> -- printenv GOMEMLIMIT
kubectl top pod -n <ns> -l app.kubernetes.io/component=bouncer
Troubleshooting: OOMKills with a low
GOMEMLIMITusually mean the controls bundle or PIP data is larger than planned — trim unused controls, reduce PIP payload size, or raise the limit with a documented capacity review. See Custom (Kubernetes / Helm).
5. Control authoring tips that preserve latency
Controls are Rego under the hood. High-frequency rules should use exact equality on hot fields (method, path prefix via data allowlists) so the policy engine can index them. Prefer data-driven allowlists from PIP / Control Plane over heavy regex.match / contains in every request.
See Rego guidelines and PBAC best practices.
Troubleshooting: If only certain routes are slow, profile which controls match those paths — a single expensive regex on a hot path can dominate P99. Prefer allowlists. Help: Troubleshooting — controls.
6. Load validation (lab)
Use a sized lab cluster (not a laptop) to prove SLA gates:
- Point traffic at the Bouncer / Envoy listener (path that does run authorization — not a health bypass).
- Run constant-arrival-rate tests at 20k RPS (P50) and 100k RPS (P99).
- Record P50/P99 and attach them to your change record.
Operator playbooks for slow evaluation: PBAC operator playbooks.
Troubleshooting: If you cannot reach target RPS, scale Bouncer replicas horizontally inside the environment (Fleet scaling caps) before changing evaluation settings.
Settings quick reference
| Area | Key settings | Default posture |
|---|---|---|
| Eval transport | OPA_UDS_PATH | Socket on |
| Hot-path I/O | CC_CONTEXT_ENRICHMENT_ENABLED | Off |
| PIP freshness | BOUNCER_PIP_STALENESS_MODE, TTLs, CC_PIP_HMAC_KEY | warn / banking→strict |
| Batch authz | BOUNCER_BATCH_AUTHZ_ENABLED, BATCH_AUTHZ_PORT | Off |
| Memory | GOMEMLIMIT + K8s limits | ~256 MiB guidance |
Next steps
- Configuration guide — full Bouncer parameter reference
- Custom (Kubernetes / Helm) — values and overlays
- PIP admin guide — attribute sources and mapping
- PEP intercept posture — TLS / JWT at the edge
- Troubleshooting