Sentinel evaluates middleware policies before proxying traffic to deployment instances. Policies are stored in the deployment’sDocumentation Index
Fetch the complete documentation index at: https://engineering.unkey.com/llms.txt
Use this file to discover all available pages before exploring further.
sentinel_config column as a JSON-serialized sentinel.v1.Config protobuf.
Evaluation flow
Evaluation model
Policies are evaluated in declaration order. For each policy:- Skip if
enabledis false. - Evaluate all match expressions. All expressions must match (AND semantics). If any expression does not match, the policy is skipped.
- Execute the policy. If it rejects the request (invalid key, rate limited, insufficient permissions), evaluation stops and sentinel returns a structured error response.
- If the policy is an auth policy and succeeds, it sets the
Principalfor the request. Subsequent auth policies are skipped.
Composability
Policies are composable building blocks. The policy list is not a set of independent checks but an ordered pipeline where earlier policies can establish context that later policies consume.Auth sets context for downstream policies
Auth policies produce a Principal containing a subject and a method-specificsource object. Today only KeyAuth is implemented; JWTAuth is defined in the protobuf schema but not yet executed by the engine (see implementation status). Downstream policies reference this principal. For example, a RateLimit policy can use the authenticated subject as its bucket key, giving each user their own rate limit window instead of a shared one.
The examples in this section illustrate the composability model. Only KeyAuth executes today; other policy types are shown to demonstrate the design.
Same policy type, different match expressions
The same policy type can appear multiple times with different match expressions. This enables path-specific or method-specific rules without requiring a single policy to handle every case. For example, applying different rate limits to different paths:/v1/expensive/foo matches both policies, so both rate limits apply independently. If the stricter limit rejects, evaluation stops and the broader policy never runs. Place more specific match expressions before broader ones so a rejection skips unnecessary work.
Layering multiple concerns
A typical production configuration layers firewall, auth, rate limiting, and validation:Full config example
Thesentinel_config column on a deployment stores a JSON-serialized sentinel.v1.Config protobuf. Here is a complete example that blocks /admin, authenticates with KeyAuth, and applies two rate limit tiers:
GET /v1/search?q=test with a valid API key:
block-adminmatch does not apply (path is/v1/search, not/admin), so the policy is skipped.api-authruns. Extracts the Bearer token, verifies it against keyspaceks_abc123, checks theapi.readpermission, and sets the Principal.search-ratelimitruns. Both match expressions pass (path starts with/v1/searchAND method is GET). Rate limits the request at 10/min using the authenticated subject as the bucket key.global-ratelimitmatch also passes (path starts with/v1/), but the request was already rate-limited by policy 3. Both policies evaluate independently.
POST /v1/keys with an invalid key:
block-adminis skipped (path does not match).api-authrejects the request with 401. Evaluation stops. Policies 3 and 4 never run.
Implementation status
The engine executes only KeyAuth. Other policy types are defined in the protobuf schema and can be configured, but the engine skips them at evaluation time.| Policy | Implemented |
|---|---|
| KeyAuth | Yes |
| Firewall | Yes |
| JWTAuth | Schema only |
| RateLimit | Schema only |
| OpenAPI validation | Schema only |
Shared types
- Policy schema for the
sentinel.v1.Policymessage structure - Match expressions for request matching rules
- Principal for the authenticated identity shape
Config parsing
The engine handles these edge cases when parsingsentinel_config:
| Input | Behavior |
|---|---|
nil or empty bytes | Pass-through (no policies) |
{} (empty JSON object) | Pass-through (legacy compatibility) |
| Valid JSON with policies | Parse and evaluate |
| Invalid JSON | Error with code Sentinel.Internal.InvalidConfiguration |
Adding a new policy type
- Define the policy proto in
svc/sentinel/proto/policies/v1/. - Add the new type to the
configoneof inpolicy.proto. - Add a case in the evaluation switch in
svc/sentinel/engine/engine.go. - Implement the executor (follow
keyauth.goas a reference). - Run
make generateto regenerate protobuf code.

