Per-IP sliding window rate limiter
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

OCaml 83.9%
Dune 4.4%
Other 11.7%
34 1 0

Clone this repository

https://tangled.org/gazagnaire.org/ocaml-rate-limit https://tangled.org/did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-rate-limit
git@git.recoil.org:gazagnaire.org/ocaml-rate-limit git@git.recoil.org:did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-rate-limit

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

rate-limit#

Per-IP sliding window rate limiter with Eio support.

Overview#

Thread-safe per-client rate limiting using the sliding window algorithm. Multi-domain safe with Eio.Mutex for concurrent access from multiple OCaml 5 domains.

Features#

  • Sliding window rate limiting (more accurate than fixed windows)
  • Per-client (IP) tracking
  • Thread-safe with Eio.Mutex
  • Configurable window size and request limit
  • Retry-after calculation returned atomically with a rejection
  • Automatic cleanup of expired entries

Installation#

Install with opam:

$ opam install rate-limit

If opam cannot find the package, it may not yet be released in the public opam-repository. Add the overlay repository, then install it:

$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install rate-limit

Usage#

check_and_record returns a decision variant so allow and reject paths can't be confused, and the retry-after delay is computed atomically with the rejection (no second lock roundtrip):

let limiter = Rate_limit.v ~max_requests:100 ~window_seconds:60.0 ()

let handle_request ~ip ~now ~process_request ~respond_429 =
  match Rate_limit.check_and_record limiter ~ip ~now with
  | Rate_limit.Allowed { remaining } ->
      Fmt.pr "Allowed, %d requests remaining@." remaining;
      process_request ()
  | Rate_limit.Rejected { retry_after } ->
      Fmt.pr "Rate limited, retry after %.0f seconds@." retry_after;
      respond_429 ~retry_after:(int_of_float retry_after)

API#

  • Rate_limit.v ?max_requests ?window_seconds () -- create a new rate limiter. Defaults: 100 requests per 60 seconds.
  • Rate_limit.check_and_record t ~ip ~now -- returns Allowed { remaining } or Rejected { retry_after }. Records the request on allow.
  • Rate_limit.retry_after t ~ip ~now -- seconds until the limit resets for this IP without recording a new request.
  • Rate_limit.current_count t ~ip ~now -- current request count for an IP in the active window.
  • Rate_limit.stats t -- (tracked_ips, total_requests) across all IPs.

Standards#

  • RFC 6585 - Additional HTTP Status Codes (429 Too Many Requests)
  • No standalone rate limiting packages found in opam
  • This implementation is Eio-native with minimal dependencies

Licence#

MIT License. See LICENSE.md for details.