Middleware chain
Every request passes through a middleware chain before reaching the proxy handler. The chain executes top-to-bottom on the request path and bottom-to-top on the response path. The order is set insvc/frontline/routes/register.go:
- PanicRecovery. Catches panics in downstream handlers so a single request cannot crash the process.
- Reserved header strip. Removes client-supplied reserved headers, including
X-Unkey-Principal, so a client cannot forge an identity. Frontline sets the verified principal itself after authentication. - Logging. Structured request logging. Skips internal paths (
/_unkey/internal/). - ClickHouseLogging. Creates a tracking context with a start timestamp and, on completion, writes the full request and response to ClickHouse. It wraps observability so it reads the final status code after observability has written the response.
- Observability. Starts an OpenTelemetry span (
frontline.proxy), records Prometheus metrics (unkey_frontline_requests_total), maps fault codes to HTTP status codes, and renders an HTML error page when the client prefers HTML. - Timeout. Enforces the configured request timeout.
Proxy handler
After the middleware chain, the proxy handler runs. Its inputs are the router service, the proxy service, and the policy engine.1. Route the hostname
The handler callsRoute(hostname) on the router. The router resolves the hostname to a frontline_route (deployment ID, sentinel_config, upstream protocol), parses the sentinel_config bytes into a policy list, and selects a destination. For a local destination the decision carries the running instances in shuffled order plus the parsed policies. If the hostname has no configured route, or the deployment has no running instance in any reachable region, the router returns a Frontline.Routing error (for example NoRunningInstances, surfaced as 503).
2. Evaluate policies
When the deployment has policies and the engine is configured, the engine evaluates each policy in order against the request. A policy that rejects the request (invalid key, rate limited, insufficient permissions) produces an error response before any byte is proxied. On success, the first authentication policy yields aPrincipal, which the handler serializes to the X-Unkey-Principal header. When the deployment has no policies, the request is forwarded without policy evaluation.