@chabdulwahab/flowcap
v1.0.4
Published
Zero-dependency, framework-agnostic rate limiting middleware. Cap the flow.
Maintainers
Readme

@chabdulwahab/flowcap
A zero-dependency, framework-agnostic HTTP rate limiting middleware for Node.js.
Features
- Framework Agnostic: Seamlessly integrates with Express, Fastify, Koa, and vanilla Node.js HTTP modules.
- Zero Dependencies: No external runtime dependencies, minimizing security risks and bundle sizes.
- Human-Readable Windows: Configure durations using intuitive strings like
'15m','30s', or'1h'. - High Performance: Implements an in-memory sliding window algorithm with O(1) automatic pruning.
- Built-in Presets: Includes pre-configured rule sets (login, api, strict, loose) for common scenarios.
- Standards Compliant: Follows the IETF draft-8 standard for RateLimit headers.
- First-Class TypeScript Support: Out-of-the-box type declarations included.
Installation
npm install @chabdulwahab/flowcap
Usage
Express
const express = require('express');
const flowcap = require('@chabdulwahab/flowcap');
const app = express();
// Apply a global rate limit of 100 requests per minute
app.use(flowcap({ limit: 100, window: '1m' }));
Built-in Presets
Presets provide default configurations for common use cases. These settings can be overridden.
// Protect login route (5 req / 15m)
app.post('/login', flowcap.login());
// Standard API limit (100 req / 1m)
app.use('/api', flowcap.api());
// Strict limit for administrative routes (20 req / 1m)
app.post('/admin', flowcap.strict());
// Loose limit for public assets (500 req / 1m)
app.get('/public', flowcap.loose());
// Override a preset configuration
app.post('/login', flowcap.login({ limit: 3 }));
Framework Support
Fastify
const fastify = require('fastify')();
const flowcap = require('@chabdulwahab/flowcap');
fastify.use(flowcap());
Koa
const Koa = require('koa');
const flowcap = require('@chabdulwahab/flowcap');
const app = new Koa();
app.use(async (ctx, next) => {
return new Promise((resolve) => {
flowcap()(ctx.req, ctx.res, () => resolve(next()));
});
});
API Reference
Configuration Options
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| limit | number | 100 | Maximum requests permitted per window. |
| window | string | number | '1m' | Window duration. Accepts readable strings (e.g., '15m', '30s') or milliseconds. |
| keyBy | function | req => req.ip | Extracts the unique identifier for the client making the request. |
| skip | function | null | Returns true to unconditionally bypass rate limiting. |
| onLimit | function | null | Custom handler for HTTP 429 Responses: (req, res, next). |
| legacyHeaders | boolean | true | Appends traditional X-RateLimit-* headers alongside IETF draft-8 standards. |
| store | Store | Memory | Instance of a custom state store. |
Advanced Configurations
Custom Client Identification
app.use(flowcap({
limit: 200,
window: '1h',
keyBy: (req) => req.headers['x-api-key'] || req.ip
}));
Conditional Bypassing
app.use(flowcap({
limit: 100,
window: '1m',
skip: (req) => req.path === '/health'
}));
Custom Rate Limit Responses
app.use(flowcap({
limit: 50,
window: '30s',
onLimit: (req, res, next) => {
res.status(429).json({ error: 'Rate limit exceeded. Please try again later.' });
}
}));
Custom Store Implementation
For distributed environments (e.g., Redis), implement the FlowcapStore interface and pass the instance to options.store.
interface FlowcapStore {
count(key: string, windowMs: number): number;
add(key: string, windowMs: number): void;
resetTime(key: string, windowMs: number): number;
}
Resources
- Deep Dive / Article: Read the detailed article on dev.to explaining the design decisions and implementation details behind Flowcap.
License
MIT
