EclipseFdn / EclipseFdn/open-vsx.org
Rate limiting — Phase 1 (Free tier enforcement + usage tracking)
- Dominant language
- TypeScript
- Stars
- 394
- Forks
- 145
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 3
Description
Deliver the minimum viable rate-limiting capabilities. Focus on correct enforcement for anonymous users and instrumentation for registered customers, plus admin controls.
## Scope
### Identity resolution (Phase 1 priority order)
- Access token (publishers) → CIDR match (registered customers) → session cookie → free/IP (anonymous).
### Data model and persistence
- Tiers stored in DB (name, RPS limits).
- Customers stored in DB with tier mapping.
- Identity bindings stored in DB (CIDR blocks).
- Global defaults stored in DB:
- Default safety valve threshold.
- Anonymous default hourly limit.
- Publisher default hourly/RPS limit.
### Runtime enforcement
- Free tier:
- Enforce **Anonymous default hourly limit** per Identity.
- Rolling 1-hour counter.
- 429 responses with standard headers and call to action.
- Registered customers:
- Always record 5-minute samples.
- Do not enforce tier limits unless `state=ENFORCEMENT` or safety valve triggers.
### Admin interface
- CRUD tiers.
- CRUD customers.
- Assign tier to customer.
- CRUD identity bindings (CIDR).
- View and manually override customer state.
- View last computed monthly p95.
- Daily computed p95 table
### Scheduled jobs
- Daily p95 computed from 5-minute samples.
- Monthly p95 computed and persisted.
- State transitions remain manual in Phase 1.
### Observability
- Hourly access counts per identity.
- Log limit-breach events (identity, source, timestamp). Example: identity=publisher:12345, source=ACCESS_TOKEN, timestamp=2026-02-20T14:05:00Z.
- Prometheus metrics exposed for Grafana dashboards.
## Suggested Technical Solution
* Implement rate limiting as a Spring Boot request filter so all traffic is evaluated in one place.
* Keep Bucket4j as the enforcement library inside the filter, while we add the new identity and tier logic around it.
* Add an identity resolution chain we can extend over time: access token → CIDR match → session cookie → IP (anonymous).
* Store global defaults, tiers, customers, and tier assignments in the existing database.
* Cache configuration in-process with Caffeine to minimise DB lookups.
* Use Redis for shared runtime counters and 5-minute usage buckets, consistent across pods.
* Enforcement:
* Free tier: keep a rolling 1-hour counter per identity key in Redis and return 429 with standard rate-limit headers.
* Registered customers: always record 5-minute buckets; enforce real-time RPS only in ENFORCEMENT or when the safety valve triggers.
* Daily p95: run a scheduled Spring job to compute daily p95 per registered customer from 5-minute buckets and persist results for reporting and charts.
* Monthly p95: run a scheduled Spring job to compute monthly p95 per registered customer, persist results. State updates remain manual in Phase 1; automation comes in Phase 3.
* Retain 5-minute buckets long enough to recompute daily/monthly p95 (Phase 1 target: 90 days).
* Observability: Micrometer Prometheus registry + Grafana dashboards, plus structured logs for limit breaches.
* Consider OpenTelemetry for distributed tracing and metrics export so the filter remains traceable as we scale.
## Acceptance criteria
- Free tier is enforced at **Anonymous default hourly limit** from release.
- Default limits and safety valve are editable via admin UI without restart.
- Identity resolution follows Phase 1 priority order.
- Registered customers have 5-minute samples stored and daily/monthly p95 computed.
- Admins can CRUD tiers/customers/CIDRs and manually set state.
- 429 responses include:
- API
- `X-RateLimit-Limit`
- `X-RateLimit-Remaining`
- `X-RateLimit-Reset`
- `Retry-After`
- Web
- Show a custom error page with a call-to-action message.
- Prometheus metrics and Grafana dashboards show usage and breaches.
- Limit-breach events are logged with the required fields (identity, source, timestamp).
## Target
15 February 2026
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.