Rules¶
A rule matches requests by path and method, and decides what share of them to let through. This page covers every field and the order rules are checked in.
Fields¶
The JSON names are what the admin API and rules files use; the Go names are fields of brownout.Rule.
| JSON | Go | Meaning |
|---|---|---|
id |
ID |
Unique name. Setting a rule with an existing ID replaces it in place, keeping its position. Required. |
path |
Path |
An exact path, or a prefix if it ends in * (/api/*). * on its own matches every path. Required. |
methods |
Methods |
Optional. Only match these HTTP methods. Names are upper-cased when stored. |
allow_percent |
AllowPercent |
Percentage of matching requests still let through, from 0 to 100. The default of 0 sheds everything. |
status_code |
StatusCode |
Status for shed requests. Defaults to 503, or the controller's WithDefaultStatus. |
retry_after_seconds |
RetryAfterSeconds |
When positive, sent as the Retry-After header. |
message |
Message |
Response body for shed requests. Defaults to the status text. |
expires_at |
ExpiresAt |
RFC 3339 time after which the rule stops applying. |
ttl |
Admin API only: a Go duration such as "15m", turned into expires_at when the rule is stored. Don't send both. |
Validation¶
A rule is rejected, and the current rules left unchanged, when:
idorpathis empty, oridisn't valid UTF-8;pathdoesn't start with/and isn't*, or has a*anywhere but the end;allow_percentis outside 0–100;status_codeis set but outside 100–599;retry_after_secondsis negative.
Replace, PUT /rules and rules files validate the whole set first: if any rule is invalid, or two share an ID, none are applied.
Matching¶
/reports/* matches /reports/, /reports/q3, /reports/q3/pdf
/reports matches /reports only
* matches everything
Prefix matching is plain string matching: /api* also matches /apiary. End the prefix with a slash, as in /api/*, to match only a path segment.
The first match decides¶
Rules are checked in the order they were added, and the first matching rule decides. If it lets a request through, because of allow_percent, later rules are never checked. Use this to carve out exceptions, by adding the narrow rule first:
c.Set(brownout.Rule{ID: "health", Path: "/api/health", AllowPercent: 100}) // always allowed
c.Set(brownout.Rule{ID: "api", Path: "/api/*"}) // everything else shed
Expired rules are skipped, as if they weren't there. Try different orders in the playground.
Partial brownouts¶
With allow_percent between 0 and 100, each matching request is let through at random with that probability. It isn't a rate limit: at 20%, a burst of 1,000 requests sends about 200 to your handler, whatever the request rate.