{"_id":"@ankitn7/rateshield","name":"@ankitn7/rateshield","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@ankitn7/rateshield","version":"1.0.0","description":"Configurable rate limiting middleware for Express.js","type":"module","main":"src/index.js","keywords":["rate-limit","rate-limiter","express","middleware","redis"],"scripts":{"dev":"nodemon demo/server.js","start":"node demo/server.js","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js --watchAll"},"author":{"name":"Ankit Nathwan"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Ankitnathwan/RateShield.git"},"bugs":{"url":"https://github.com/Ankitnathwan/RateShield/issues"},"homepage":"https://github.com/Ankitnathwan/RateShield","dependencies":{"redis":"^6.2.1"},"peerDependencies":{"express":">=5.0.0"},"devDependencies":{"@jest/globals":"^30.4.1","express":"^5.2.1","jest":"^30.4.2","nodemon":"^3.1.14","supertest":"^7.2.2"},"_id":"@ankitn7/rateshield@1.0.0","gitHead":"3f4ae7db878d6d9b388c729923cdc5ac98de937f","_nodeVersion":"22.19.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-u6sCphrQ8Ko8BJi1UpNZtMPpz4emVGyO6lJ19nRYRx84nQB70Ycw2oycEyCqlO5+JZf1Q6glSWR733S2ph71Wg==","shasum":"a18b9d1883690365e16896e67ac0259955da81d7","tarball":"https://registry.npmjs.org/@ankitn7/rateshield/-/rateshield-1.0.0.tgz","fileCount":13,"unpackedSize":26964,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC7LXf7XNY+/zf8FArZg8O82YxxFw9Dp2t9V5McGUewHgIgZ1cc+gegODPY8+68NF0r2zUJDmeV7Q0OdPSe9F5ixBc="}]},"_npmUser":{"name":"ankitn7","email":"ankitnathwan112@gmail.com"},"directories":{},"maintainers":[{"name":"ankitn7","email":"ankitnathwan112@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/rateshield_1.0.0_1789071442246_0.97423589696674"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-10T20:17:22.043Z","1.0.0":"2026-09-10T20:17:22.384Z","modified":"2026-09-10T20:17:22.669Z"},"maintainers":[{"name":"ankitn7","email":"ankitnathwan112@gmail.com"}],"description":"Configurable rate limiting middleware for Express.js","homepage":"https://github.com/Ankitnathwan/RateShield","keywords":["rate-limit","rate-limiter","express","middleware","redis"],"repository":{"type":"git","url":"git+https://github.com/Ankitnathwan/RateShield.git"},"author":{"name":"Ankit Nathwan"},"bugs":{"url":"https://github.com/Ankitnathwan/RateShield/issues"},"license":"MIT","readme":"# RateShield\n\nConfigurable and extensible rate-limiting middleware for Express.js.\n\nRateShield provides multiple rate-limiting algorithms, pluggable storage backends, customizable client identification, rate-limit response headers, and an async-first architecture designed to support both in-memory and Redis-backed rate limiting.\n\n## Features\n\n* Multiple rate-limiting algorithms\n\n  * Fixed Window\n  * Sliding Window\n  * Token Bucket\n* Pluggable storage backends\n\n  * In-memory storage\n  * Redis\n* Custom client key generation\n* Standard `X-RateLimit-*` response headers\n* Atomic rate limiting with Redis\n* Async-first storage architecture\n* Input and result validation\n* Express.js middleware integration\n* Comprehensive Jest test suite\n* Integration tests using Supertest\n* Concurrency testing for rate limiting\n\n## Installation\n\n```bash\nnpm install rateshield\n```\n\n## Quick Start\n\n```javascript\nimport express from \"express\";\nimport { rateLimiter } from \"rateshield\";\n\nconst app = express();\n\napp.use(\n    rateLimiter({\n        algorithm: \"fixed-window\",\n        limit: 100,\n        windowMs: 60_000,\n    })\n);\n\napp.get(\"/\", (req, res) => {\n    res.json({\n        message: \"Hello from RateShield\",\n    });\n});\n\napp.listen(3000);\n```\n\nBy default, RateShield uses the client's IP address as the rate-limit key.\n\n## Algorithms\n\nRateShield currently supports three rate-limiting algorithms.\n\n### Fixed Window\n\nFixed Window divides time into fixed intervals and limits the number of requests allowed during each interval.\n\n```javascript\nrateLimiter({\n    algorithm: \"fixed-window\",\n    limit: 100,\n    windowMs: 60_000,\n});\n```\n\nIn this example, each client can make up to 100 requests during a 60-second window.\n\n**Characteristics:**\n\n* Simple and efficient\n* Low memory overhead\n* Easy to understand and implement\n* Can allow bursts around window boundaries\n\n### Sliding Window\n\nSliding Window tracks request timestamps and evaluates requests against a continuously moving time window.\n\n```javascript\nrateLimiter({\n    algorithm: \"sliding-window\",\n    limit: 100,\n    windowMs: 60_000,\n});\n```\n\nThis provides smoother rate limiting than a fixed window because the limit is based on the requests that occurred during the most recent time interval.\n\n**Characteristics:**\n\n* More accurate than Fixed Window\n* Reduces boundary bursts\n* Stores request timestamps\n* Higher memory usage for high request volumes\n\n### Token Bucket\n\nToken Bucket maintains a bucket of tokens that are consumed by requests and continuously refilled over time.\n\n```javascript\nrateLimiter({\n    algorithm: \"token-bucket\",\n    capacity: 100,\n    refillRate: 1,\n});\n```\n\n`capacity` determines the maximum number of tokens that can be stored.\n\n`refillRate` determines how many tokens are added per second.\n\nFor example:\n\n```javascript\nrateLimiter({\n    algorithm: \"token-bucket\",\n    capacity: 10,\n    refillRate: 2,\n});\n```\n\nThis allows bursts of up to 10 requests when the bucket is full, while replenishing tokens at a rate of 2 per second.\n\n**Characteristics:**\n\n* Supports controlled bursts\n* Smooth request throttling\n* Continuous token replenishment\n* Fractional tokens can be maintained internally\n\n## Storage\n\nRateShield separates rate-limiting algorithms from their storage implementation.\n\nThe architecture allows different storage backends to be plugged into the algorithms.\n\n### MemoryStore\n\n`MemoryStore` stores rate-limit state in the Node.js process using a JavaScript `Map`.\n\nIt is useful for:\n\n* Local development\n* Testing\n* Single-process applications\n* Simple deployments\n\nExample:\n\n```javascript\nimport { rateLimiter, MemoryStore, } from \"rateshield\";\n\nrateLimiter({\n    algorithm: \"fixed-window\",\n    limit: 100,\n    windowMs: 60_000,\n    store: new MemoryStore(),\n});\n```\n\nThe default configuration uses an in-memory store.\n\n### RedisStore\n\n`RedisStore` allows rate-limit state to be shared through Redis.\n\nThis is useful when an application runs across multiple processes or server instances.\n\nExample:\n\n```javascript\nimport { rateLimiter, RedisStore, } from \"rateshield\";\n\nconst store = new RedisStore({\n    url: \"redis://localhost:6379\",\n});\n\napp.use(\n    rateLimiter({\n        algorithm: \"fixed-window\",\n        limit: 100,\n        windowMs: 60_000,\n        store,\n    })\n);\n```\n\nYou can also configure Redis through the `REDIS_URL` environment variable:\n\n```env\nREDIS_URL=redis://localhost:6379\n```\n\nThen:\n\n```javascript\nconst store = new RedisStore();\n```\n\nRedis-backed Fixed Window rate limiting uses an atomic Redis operation to prevent concurrent requests from incorrectly exceeding the configured limit.\n\n## Custom Key Generator\n\nBy default, RateShield identifies clients using their IP address:\n\n```javascript\n(req) => req.ip\n```\n\nYou can provide your own key generator.\n\nFor example, to rate-limit using an API key:\n\n```javascript\nrateLimiter({\n    algorithm: \"fixed-window\",\n    limit: 100,\n    windowMs: 60_000,\n\n    keyGenerator: (req) => {\n        return req.headers[\"x-api-key\"];\n    },\n});\n```\n\nYou can also use authenticated user IDs:\n\n```javascript\nrateLimiter({\n    algorithm: \"fixed-window\",\n    limit: 100,\n    windowMs: 60_000,\n\n    keyGenerator: (req) => {\n        return req.user.id;\n    },\n});\n```\n\nThis allows applications to choose the appropriate rate-limiting strategy for their authentication and API architecture.\n\n## Rate Limit Headers\n\nRateShield adds rate-limit information to responses using the following headers:\n\n```text\nX-RateLimit-Limit\nX-RateLimit-Remaining\nX-RateLimit-Reset\n```\n\nExample:\n\n```text\nX-RateLimit-Limit: 100\nX-RateLimit-Remaining: 97\nX-RateLimit-Reset: 1726000000000\n```\n\nWhen the configured limit is exceeded, RateShield responds with:\n\n```http\n429 Too Many Requests\n```\n\nand:\n\n```json\n{\n    \"error\": \"Too many requests\"\n}\n```\n\n## Configuration\n\n### Fixed Window / Sliding Window\n\n```javascript\nrateLimiter({\n    algorithm: \"fixed-window\",\n    limit: 100,\n    windowMs: 60_000,\n});\n```\n\n| Option         | Type       | Description                            |\n| -------------- | ---------- | -------------------------------------- |\n| `algorithm`    | `string`   | `\"fixed-window\"` or `\"sliding-window\"` |\n| `limit`        | `integer`  | Maximum requests allowed               |\n| `windowMs`     | `integer`  | Window duration in milliseconds        |\n| `store`        | `Store`    | Storage backend                        |\n| `keyGenerator` | `function` | Generates the client identifier        |\n\n### Token Bucket\n\n```javascript\nrateLimiter({\n    algorithm: \"token-bucket\",\n    capacity: 100,\n    refillRate: 1,\n});\n```\n\n| Option         | Type       | Description                     |\n| -------------- | ---------- | ------------------------------- |\n| `algorithm`    | `string`   | `\"token-bucket\"`                |\n| `capacity`     | `integer`  | Maximum number of tokens        |\n| `refillRate`   | `number`   | Tokens added per second         |\n| `store`        | `Store`    | Storage backend                 |\n| `keyGenerator` | `function` | Generates the client identifier |\n\n## Default Configuration\n\nCalling:\n\n```javascript\nrateLimiter();\n```\n\nuses the following defaults:\n\n```javascript\n{\n    algorithm: \"fixed-window\",\n    limit: 100,\n    windowMs: 60_000,\n    store: new MemoryStore(),\n    keyGenerator: (req) => req.ip,\n}\n```\n\n## Architecture\n\nRateShield separates the middleware, algorithms, and storage layers.\n\n```text\n                    Express Request\n                           │\n                           ▼\n                   RateLimiter Middleware\n                           │\n                           ▼\n                    Algorithm Registry\n                           │\n          ┌────────────────┼────────────────┐\n          ▼                ▼                ▼\n     Fixed Window     Sliding Window    Token Bucket\n          │                │                │\n          └────────────────┼────────────────┘\n                           ▼\n                     Store Interface\n                           │\n                  ┌────────┴────────┐\n                  ▼                 ▼\n             MemoryStore       RedisStore\n```\n\n### Why this architecture?\n\nThe algorithms do not need to know how data is stored.\n\nFor example:\n\n```text\nFixedWindow\n     │\n     ▼\n   Store\n     │\n ┌───┴────┐\n ▼        ▼\nMemory   Redis\n```\n\nThis makes the system easier to extend and test.\n\nA new storage backend can implement the required store operations without changing the rate-limiting algorithms.\n\n## Async-First Design\n\nRateShield uses an async-first storage architecture.\n\nEven though `MemoryStore` operates locally in memory, its interface is asynchronous:\n\n```javascript\nawait store.get(key);\nawait store.set(key, value);\n```\n\nThis allows the same algorithm implementation to work with both local and network-based storage.\n\n```text\nMemoryStore → async → Map\nRedisStore  → async → Redis\n```\n\nThis avoids coupling the algorithms to a specific storage implementation.\n\n## Validation\n\nRateShield validates configuration options before creating a rate limiter.\n\nExamples of validated values include:\n\n* Supported algorithm names\n* Positive request limits\n* Positive window durations\n* Positive token bucket capacity\n* Positive refill rates\n* Valid key generator functions\n\nAlgorithm results are also validated before being used by the middleware.\n\nExpected algorithm result:\n\n```javascript\n{\n    allowed: true,\n    limit: 100,\n    remaining: 99,\n    resetTime: 1726000000000,\n}\n```\n\nThis provides a consistent contract between algorithms and the middleware.\n\n## Testing\n\nRateShield uses Jest for automated testing.\n\nThe test suite covers:\n\n* Fixed Window behavior\n* Sliding Window behavior\n* Token Bucket behavior\n* MemoryStore\n* RedisStore\n* Store contract compatibility\n* Configuration validation\n* Result validation\n* Custom key generators\n* Middleware behavior\n* Express integration\n* Concurrency behavior\n\nRun the test suite with:\n\n```bash\nnpm test -- --runInBand\n```\n\nThe project also includes integration tests using Supertest to verify RateShield behavior through an actual Express application.\n\n## Benchmarks\n\nRateShield includes a benchmark suite for comparing algorithm performance.\n\nRun:\n\n```bash\nnode benchmarks/algorithms.js\n```\n\nBenchmarking is currently focused on comparing the computational characteristics of the supported algorithms.\n\nPerformance results can vary depending on hardware, Node.js version, workload, and configuration.\n\n## Project Structure\n\n```text\nRateShield/\n├── src/\n│   ├── algorithms/\n│   │   ├── FixedWindow.js\n│   │   ├── SlidingWindow.js\n│   │   ├── TokenBucket.js\n│   │   └── index.js\n│   │\n│   ├── middleware/\n│   │   └── rateLimiter.js\n│   │\n│   ├── stores/\n│   │   ├── MemoryStore.js\n│   │   └── RedisStore.js\n│   │\n│   ├── utils/\n│   │   ├── validateOptions.js\n│   │   └── validateResult.js\n│   │\n│   └── index.js\n│\n├── demo/\n│   ├── app.js\n│   └── server.js\n│\n├── tests/\n│   ├── middleware/\n│   └── integration/\n│\n├── benchmarks/\n│   └── algorithms.js\n│\n├── package.json\n└── README.md\n```\n\n## Roadmap\n\nPlanned improvements include:\n\n* Additional rate-limiting algorithms\n* Further Sliding Window optimization\n* Improved Redis key isolation\n* More configurable response behavior\n* Additional storage adapters\n* Better package documentation\n* Production deployment examples\n* Additional performance benchmarks\n* npm package publication\n\n## Contributing\n\nContributions, suggestions, and improvements are welcome.\n\nIf you find a bug or have an idea for a feature, open an issue or submit a pull request.\n\n## License\n\nMIT License\n\nCopyright (c) 2026 Ankit Nathwan\n\nSee the `LICENSE` file for the full license text.\n\n## Author\n\n**Ankit Nathwan**\n\nGitHub:\nhttps://github.com/Ankitnathwan/RateShield\n","readmeFilename":"README.md","_rev":"1-97dd70ad15f76a21c9ef532c63607b20"}