3.0 KiB
Executable File
3.0 KiB
Executable File
Quota Enforcement — Flow Diagram (rev 2.1)
Scope – this document explains how the free‑tier limits are enforced
inside the scanner service. For policy rationale and legal aspects see
33_333_QUOTA_OVERVIEW.md
.
0 · Key parameters (rev 2.1)
Symbol | Value | Meaning |
---|---|---|
L_anon |
{{ quota_anon }} | Daily ceiling for anonymous users |
L_jwt |
{{ quota_token }} | Daily ceiling for token holders |
T_warn |
200 |
Soft reminder threshold |
D_soft |
5 000 ms |
Delay for first 30 over‑quota scans |
D_hard |
60 000 ms |
Delay for all scans beyond the soft window |
L_active
is L_jwt
if a valid token is present; else L_anon
.
1 · Sequence diagram
sequenceDiagram
participant C as Client
participant API as Scanner API
participant REDIS as Redis (quota)
C->>API: /scan
API->>REDIS: INCR quota:<key>
REDIS-->>API: new_count
alt new_count ≤ L_active
API-->>C: 202 Accepted (no delay)
else new_count ≤ L_active + 30
API->>C: wait D_soft
API-->>C: 202 Accepted
else
API->>C: wait D_hard
API-->>C: 202 Accepted
end
Counters auto‑expire 24 h after first increment (00:00 UTC reset).
2 · Redis key layout
Key pattern | TTL | Description |
---|---|---|
quota:ip:<sha256> |
24 h | Anonymous quota per hashed IP |
quota:tid:<sha256> |
24 h | Token quota per hashed token‑ID |
quota:ip:<sha256>:ts |
24 h | First‑seen timestamp (ISO 8601) |
Keys share a common TTL for efficient mass expiry via redis-cli --scan
.
3 · Pseudocode (Go‑style)
func gate(key string, limit int) (delay time.Duration) {
cnt, _ := rdb.Incr(ctx, key).Result()
switch {
case cnt <= limit:
return 0 // under quota
case cnt <= limit+30:
return 5 * time.Second
default:
return 60 * time.Second
}
}
The middleware applies time.Sleep(delay)
before processing the scan
request; it never returns HTTP 429
under the free tier.
4 · Metrics & monitoring
Metric | PromQL sample | Alert |
---|---|---|
stella_quota_soft_hits_total |
increase(...[5m]) > 50 |
Many users near limit |
stella_quota_hard_hits_total |
rate(...[1h]) > 0.1 |
Potential abuse |
Average delay per request | histogram_quantile(0.95, sum(rate(...))) |
P95 < 1 s expected |
Generated {{ "now" | date: "%Y‑%m‑%d" }} — values pulled from central constants.