Skip to content

[Task]: Add rate limiting to public registry and orchestrator write endpoints #90

Description

@grantfox-oss

The registry (POST /register, POST /feedback) and the orchestrator (POST /api/tasks) expose write endpoints with no rate limiting. On a public testnet deployment this invites accidental or deliberate abuse: a loop hammering POST /register floods registry.json writes (even behind the write queue), and repeated POST /api/tasks spins up unbounded planning work and real Anthropic spend. Per-IP rate limiting is the standard, cheap mitigation.

Goal

Apply per-IP rate limiting to the write endpoints of both services, tuned so normal usage is never affected but abuse is capped.

Requirements & constraints

  • Limit the write endpoints only; read/liveness endpoints stay unlimited or get a much looser limit.
  • /health must never be throttled — Render's platform health checks hit it continuously and a 429 there would flap the service.
  • Limits are configurable via env vars (e.g. RATE_LIMIT_WRITES_PER_MIN) with documented defaults; the orchestrator's task endpoint should be stricter than the registry's write endpoints.
  • Exceeding a limit returns HTTP 429 with a clear JSON body.
  • trust proxy must be configured for Render so the limiter keys on the real client IP, not the load-balancer IP (otherwise all traffic shares one bucket). Verify this explicitly.

Design decisions left to the implementer

  • Library vs hand-rolled. express-rate-limit is conventional; a tiny in-memory token bucket keeps it dependency-free. Either is acceptable — note the memory/coldstart implications on Render (in-memory limits reset on redeploy; that's fine for this scope).

Edge cases to consider

  • Multiple services behind the same proxy — confirm IPs are distinguished correctly after trust proxy.
  • A burst exactly at the limit boundary (Nth request allowed, N+1 blocked).
  • Health/readiness checks under load must keep returning 200.

Acceptance criteria

  • Write endpoints on registry and orchestrator are per-IP rate limited
  • Limits configurable via env with documented defaults; task endpoint stricter than registry writes
  • /health (and other liveness routes) exempt
  • Over-limit returns 429 with a clear body
  • trust proxy correctly configured for Render (verified, not assumed)
  • Tests: a burst past the limit yields 429; normal usage unaffected; /health never throttled
  • npm test passes; limits documented in docs/development.md + .env.example

Relevant files

  • packages/registry/src/server.ts, packages/orchestrator/src/server.ts, docs/development.md, .env.example

Notes for contributors

If you'd like to work on this, comment below so we can assign it to you.
Questions welcome — see CONTRIBUTING.md for setup
and workflow.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions