Security
Rate Limiting
Protect your API from brute-force attacks and abuse.
Rate Limit
Limit the number of requests a client can make within a time window.
Installation
bun add @bklarjs/rate-limitnpm install @bklarjs/rate-limitUsage
import { rateLimit } from "@bklarjs/rate-limit";
// Limit to 100 requests per 15 minutes
app.use(
rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
message: "Too many requests, please try again later.",
})
);Custom Key Generator
By default, it limits by IP. You can limit by API Key or User ID.
app.use(
rateLimit({
keyGenerator: (ctx) => {
// Limit by Authenticated User ID
return ctx.state.jwt?.sub || ctx.req.headers.get("x-api-key");
},
})
);Skip Requests
Use skip when you need to bypass the rate limiter entirely for specific requests,
such as trusted internal traffic, health checks, or monitoring endpoints.
If skip returns true, the middleware immediately calls next() without
tracking hits or attaching any X-RateLimit-* headers.
app.use(
rateLimit({
windowMs: 60 * 1000,
max: 100,
skip: (ctx) => ctx.req.headers.get("user-agent") === "HealthChecker",
})
);Trusted IP Example
When your app sits behind reverse proxies like Cloudflare, use forwarded headers to inspect the real client IP before deciding whether to skip rate limiting.
import { rateLimit } from "@bklarjs/rate-limit";
const trustedIps = ["127.0.0.1", "192.168.1.50"];
app.use(
rateLimit({
windowMs: 60 * 1000,
max: 100,
skip: (ctx) => {
// Extract the true client IP (considering reverse proxies like Cloudflare)
const ip =
ctx.req.headers.get("x-forwarded-for")?.split(",")[0].trim() ||
ctx.req.headers.get("cf-connecting-ip") ||
"unknown";
// If the IP is in our trusted list, skip rate limiting
return trustedIps.includes(ip);
}
})
);