What it checks
The deny checks run first, so a denied client never spends a rate token. The rate limit is a token bucket per client address:
rps is the refill rate, burst the bucket size. A rate of 0 turns the limit off and leaves the lists.
Modes
Move from
log_only to enforce once the replay shows nothing you want to keep would be blocked. The dashboard only offers enforcing after the replay for the current settings has loaded.
Client address
The client address is the one the access log and firewall use: the TCP peer, unless it is a configured trusted proxy, in which case the forwarded header is read from the right, skipping trusted hops. A forwarded header from any other peer is ignored, so a client cannot dodge a limit or frame someone else by sendingX-Forwarded-For. Behind a proxy that hides client addresses and with no trusted proxies set, the status shows ClientIPHidden: every visitor would share one limit.
Status
Each policy reports a condition with a reason:Enforcing, LogOnly, Off, NoRoutes (the app has no proxied route, for example a static site or a stopped app), ClientIPHidden, InvalidPolicy or Pending (waiting for the next ingress pass).
Fail open
The defense never takes an app down. If the policy store cannot be read, the stored policy is invalid, or evaluating a request panics, the request is served and afail_open counter goes up. The dashboard and apps abuse get show it.
Counters
Per app, per window, in the traffic view and metrics:allowed, would_block and blocked by reason (rate_limit, deny_cidr, deny_user_agent, missing_user_agent), and fail_open. Metric names start with http_abuse_.
Replay before you enforce
The replay runs the last minutes of the control plane’s in-memory access log through a draft policy and reports how many requests it would have blocked and which clients were hit most. It reads memory only and changes nothing. Client addresses and User-Agents are kept in memory for this and are never returned by the access log API or written to disk, so the replay covers only what the log still holds (a restart empties it) and needs theread:sensitive ability.
- Dashboard
- CLI
- API
Open the app, then Traffic. The Abuse defense card shows the mode, the per-client rate (prefilled from the app’s recent peak), the block lists and a live preview of what the draft would have blocked.
Limits and tuning
All caps and defaults come from the environment, never from code. Every variable is optional.
Memory is bounded by
APP_ABUSE_MAX_TRACKED_CLIENTS per app. When a shard is full, an arbitrary tracked client is dropped, so a flood of distinct addresses cannot grow memory. Static sites served directly by the ingress are not covered yet.