@sigil-dev/plugin-ratelimit
v0.9.26
Published
Per-client request rate limits for Grimoire, in memory or Redis
Readme
@sigil-dev/plugin-ratelimit
Per-visitor request limits for Grimoire, in memory or in Redis.
// sigil.config.ts
import { rateLimit, redis } from "@sigil-dev/plugin-ratelimit";
export default defineConfig({
plugins: [
rateLimit({
max: 100, // per minute, per visitor
routes: {
// five sign-in attempts a minute; visiting the page doesn't count
"/login": { max: 5, methods: ["POST"] },
},
backend: redis({ url: Bun.env.REDIS_URL }), // "memory" (the default) is per worker
}),
],
});A request over its limit gets a 429 with Retry-After; every response carries X-RateLimit-Limit, -Remaining and -Reset.
- Each route limit has its own allowance. Browsing the site doesn't use up the five sign-in attempts, and sign-in attempts don't use up the site-wide 100.
- A route covers whole path segments:
/apilimits/apiand/api/users, not/apiary. The most specific route wins. - The visitor is found the way Grimoire finds them (
clientAddress): behind a reverse proxy on the same machine or private network, the address the proxy reports; otherwise the connection's own, so a visitor can't dodge the limit by sending a made-upX-Forwarded-For. Undersigil startthe coordinator passes the address to the workers.
| Option | Default | |
| --- | --- | --- |
| max | 100 | Requests per window |
| windowMs | 60_000 | Window length |
| routes | none | { "/path": { max, windowMs, methods } } |
| keyBy | the visitor's IP | (req, server) => string |
| skip | none | (req) => boolean, for health checks and trusted callers |
| backend | "memory" | "memory" or redis({ url, keyPrefix }) |
| message | Too Many Requests | The 429 body |
