Problem. internal/ws/limiter.go caps concurrent connections per IP (default 5) but not the connect rate, so connect/close churn is free. When the cap trips, the handler answers 429 on the upgrade (handler.go:62); browsers hide upgrade status, so the client sees a bare close 1006 and retries on its normal 1–30 s ladder.
Ask.
- Add a per-IP upgrade-rate limit (e.g. 10/min) next to the concurrent cap, config
websocket.max_connects_per_minute.
- When shedding an already-accepted socket, close with code 1013 (try again later) or 1008; beacon-web pins its backoff to the 30 s maximum on those codes (
ws-manager.ts, 2026-09-02).
- Optional: emit the contract's WS
rate_limited error for a subscribe whose scope spans more than N IATAs (api_contract.md:957); today one connection can subscribe to everything.
Problem.
internal/ws/limiter.gocaps concurrent connections per IP (default 5) but not the connect rate, so connect/close churn is free. When the cap trips, the handler answers 429 on the upgrade (handler.go:62); browsers hide upgrade status, so the client sees a bare close 1006 and retries on its normal 1–30 s ladder.Ask.
websocket.max_connects_per_minute.ws-manager.ts, 2026-09-02).rate_limitederror for a subscribe whose scope spans more than N IATAs (api_contract.md:957); today one connection can subscribe to everything.