Skip to content

Rate limiter is per-process: N instances = N× the Chess.com per-IP request rate #111

Description

@Sootopolis

Problem

The Chess.com client's admission control — the min-request-delay pacer (lastRequestRef), the permit gate/Semaphore, the failure-window throttle-down, EMA spacing — is entirely in-process (Ref / Semaphore), created fresh per ChessComClient.live. There is no shared/DB-backed coordination.

So N processes = N independent rate limiters. Two CcasServer instances (or a server + a heavy CLI run) on the same machine/NAT share one egress IP but each enforces its own budget → combined load ≈ N× the ~13.3 req/s the single-process pacer was tuned to hold. The whole client (75ms min-request-delay floor; CF-403 count = 0 across ~524k requests / 32 days) was tuned assuming one limiter per IP. Doubling it risks 429 / Cloudflare-403 storms.

Evidence

  • ChessComClient throttle state (ThrottleState ref, active-count ref, gate Semaphore, lastRequestRef) is all in-memory, instantiated per layer; emaDelay / recordOutcome / throttleDown touch only local refs, no DB.
  • Only DB interaction is stats flushing, not live admission state.
  • Surfaced by the multi-instance concurrency audit (2026-06-23).

Relief path

Bearer-token OAuth on /pub requests bypasses the per-IP rate limit (noted previously), which dissolves the shared-IP contention for the real dev-laptop-vs-prod case. That's part of #60 / auth work. A DB/Redis-backed global token bucket would be the alternative if unauthenticated multi-process ever needs to coexist.

Status

Single server per DB is the documented supported model; CLI-alongside-server shares this egress concern but is bursty/tiny. Latent for multi-server hosting (#60). Capturing so it isn't a surprise when concurrency becomes real.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:clientChess.com HTTP client, cache, rate limitingenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions