Skip to content

@jfungus/ratelimit-h3

Rate limiting middleware for H3 and Nitro - the universal JavaScript server framework.

Installation

Terminal window
npm install @jfungus/ratelimit-h3

Basic Usage

import { createApp, eventHandler } from "h3";
import { rateLimiter } from "@jfungus/ratelimit-h3";
const app = createApp();
app.use(
rateLimiter({
limit: 100,
windowMs: 60 * 1000, // 1 minute
}),
);
app.use(eventHandler(() => "Hello!"));
export default app;

Nitro Server Middleware

server/middleware/ratelimit.ts
import { rateLimiter } from "@jfungus/ratelimit-h3";
export default rateLimiter({
limit: 100,
windowMs: 60 * 1000, // 1 minute
});

Options

OptionTypeDefaultDescription
limitnumber | (event) => number60Max requests per window
windowMsnumber60000Window duration in ms
algorithm'fixed-window' | 'sliding-window''sliding-window'Algorithm
storeRateLimitStoreMemoryStoreStorage backend
keyGenerator(event) => stringIP-basedClient identifier
skip(event) => boolean-Skip rate limiting
handler(event, info) => void429 responseCustom handler

Access Rate Limit Info

server/api/data.ts
export default eventHandler((event) => {
const info = event.context.rateLimit;
// { limit: 100, remaining: 99, reset: 1234567890 }
return { data: "hello" };
});

Custom Key Generator

import { getHeader, getRequestIP } from "h3";
app.use(
rateLimiter({
limit: 100,
windowMs: 60 * 1000, // 1 minute
keyGenerator: (event) => {
return getHeader(event, "x-user-id") ?? getRequestIP(event) ?? "unknown";
},
}),
);

With Redis

server/plugins/ratelimit.ts
import { createStorage } from "unstorage";
import redisDriver from "unstorage/drivers/redis";
import { createUnstorageStore } from "@jfungus/ratelimit-unstorage";
export const rateLimitStore = createUnstorageStore({
storage: createStorage({
driver: redisDriver({ url: process.env.REDIS_URL }),
}),
});
// server/middleware/ratelimit.ts
import { rateLimiter } from "@jfungus/ratelimit-h3";
import { rateLimitStore } from "../plugins/ratelimit";
export default rateLimiter({
limit: 100,
windowMs: 60 * 1000, // 1 minute
store: rateLimitStore,
});