Multi-framework rate limiting for JavaScript/TypeScript.
- Multi-Framework - Works with Hono, Express, H3/Nitro, Nuxt
- Smart Algorithms - Fixed window and sliding window (Cloudflare-style)
- Flexible Storage - Memory, Redis, Cloudflare KV, Vercel KV, and more
- TypeScript First - Full type support with comprehensive definitions
- Zero Dependencies - Core package has no external dependencies
# For Hono
npm install @jfungus/ratelimit-hono
# For Express
npm install @jfungus/ratelimit-express
# For H3/Nitro
npm install @jfungus/ratelimit-h3
# For Nuxt
npm install @jfungus/ratelimit-nuxtimport { Hono } from "hono";
import { rateLimiter } from "@jfungus/ratelimit-hono";
const app = new Hono();
app.use(
rateLimiter({
limit: 100, // 100 requests
windowMs: 60 * 1000, // per 1 minute
}),
);
app.get("/", (c) => c.text("Hello!"));That's it! Your API is now rate limited.
| Option | Type | Default | Description |
|---|---|---|---|
limit |
number |
100 |
Max requests per window |
windowMs |
number |
60 * 1000 |
Window size in milliseconds (1 minute) |
algorithm |
string |
"sliding-window" |
"sliding-window" or "fixed-window" |
keyGenerator |
function |
IP-based | Function to identify clients |
skip |
function |
- | Skip rate limiting for certain requests |
handler |
function |
429 response | Custom rate limit exceeded handler |
store |
Store |
MemoryStore |
Custom storage backend |
windowMs: 1000; // 1 second
windowMs: 60 * 1000; // 1 minute
windowMs: 5 * 60 * 1000; // 5 minutes
windowMs: 15 * 60 * 1000; // 15 minutes
windowMs: 60 * 60 * 1000; // 1 hourSee all options in documentation
| Package | Description |
|---|---|
@jfungus/ratelimit |
Core library with algorithms and MemoryStore |
@jfungus/ratelimit-hono |
Hono middleware |
@jfungus/ratelimit-express |
Express middleware |
@jfungus/ratelimit-h3 |
H3/Nitro middleware |
@jfungus/ratelimit-nuxt |
Nuxt module |
@jfungus/ratelimit-unstorage |
Adapter for Redis, Cloudflare KV, etc. |
import express from "express";
import { rateLimiter } from "@jfungus/ratelimit-express";
const app = express();
app.use(
rateLimiter({
limit: 100,
windowMs: 15 * 60 * 1000, // 15 minutes
}),
);import { createApp } from "h3";
import { rateLimiter } from "@jfungus/ratelimit-h3";
const app = createApp();
app.use(
rateLimiter({
limit: 100,
windowMs: 60 * 1000, // 1 minute
}),
);// nuxt.config.ts
export default defineNuxtConfig({
modules: ["@jfungus/ratelimit-nuxt"],
rateLimit: {
limit: 100,
windowMs: 60 * 1000, // 1 minute
},
});app.use(
rateLimiter({
limit: 100,
windowMs: 60 * 1000,
keyGenerator: (c) => c.req.header("X-API-Key") ?? "anonymous",
}),
);import { createStorage } from "unstorage";
import redisDriver from "unstorage/drivers/redis";
import { createUnstorageStore } from "@jfungus/ratelimit-unstorage";
const storage = createStorage({
driver: redisDriver({ url: "redis://localhost:6379" }),
});
app.use(
rateLimiter({
limit: 100,
windowMs: 60 * 1000,
store: createUnstorageStore({ storage }),
}),
);Cloudflare-style weighted sliding window for smoother rate limiting:
rateLimiter({
algorithm: "sliding-window",
limit: 100,
windowMs: 60 * 1000,
});Simple counter that resets at fixed intervals:
rateLimiter({
algorithm: "fixed-window",
limit: 100,
windowMs: 60 * 1000,
});Contributions are welcome! Please read our Contributing Guide for details.
MIT