Muke Johnbaptist
August 26, 2024
Rate limiting is an essential strategy for protecting web applications and APIs from abuse, such as denial-of-service (DoS) attacks, brute-force attacks, and excessive usage. By controlling the number of requests a user can make to your server, you can ensure fair usage and maintain the stability of your application.
In this blog, we'll explore how to implement rate limiting in a Node.js application using Express and TypeScript. We'll dive into two libraries that are particularly effective for this purpose:
Let's get started!
Before we implement rate limiting, let's set up a basic Node.js and Express application with TypeScript.
mkdir rate-limiting-app cd rate-limiting-app npm init -y
npm install express express-rate-limit express-slow-down npm install typescript @types/node @types/express ts-node --save-dev
{ "compilerOptions": { "target": "ES6", "module": "commonjs", "strict": true, "esModuleInterop": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"] }
import express, { Request, Response } from 'express'; const app = express(); app.get('/', (req: Request, res: Response) => { res.send('Welcome to the Rate Limiting Demo!'); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
npx ts-node src/index.ts
Now that we have our basic Express server set up, let's implement rate limiting.
express-rate-limit is a simple yet powerful library that allows you to block excessive requests from a single IP address.
npm install express-rate-limit
import express, { Request, Response } from 'express'; import rateLimit from 'express-rate-limit'; const app = express(); // Configure rate limiter const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // Limit each IP to 100 requests per `window` (here, per 15 minutes) message: 'Too many requests from this IP, please try again later.', }); // Apply the rate limiter to all requests app.use(limiter); app.get('/', (req: Request, res: Response) => { res.send('Welcome to the Rate Limiting Demo!'); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
With this configuration, a user can make up to 100 requests every 15 minutes from a single IP address. If they exceed this limit, they’ll receive an error message.
While blocking requests is effective, sometimes you may prefer to slow down the requests instead of blocking them outright. This is where express-slow-down comes into play.
npm install express-slow-down
import express, { Request, Response } from 'express'; import rateLimit from 'express-rate-limit'; import slowDown from 'express-slow-down'; const app = express(); // Configure rate limiter const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // Limit each IP to 100 requests per `window` (here, per 15 minutes) message: 'Too many requests from this IP, please try again later.', }); // Configure slow down middleware const speedLimiter = slowDown({ windowMs: 15 * 60 * 1000, // 15 minutes delayAfter: 50, // Allow 50 requests per 15 minutes, then... delayMs: 500, // Begin adding 500ms of delay per request above 50 }); // Apply the rate limiter to all requests app.use(limiter); app.use(speedLimiter); app.get('/', (req: Request, res: Response) => { res.send('Welcome to the Rate Limiting Demo!'); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });
In this setup, the server allows up to 50 requests within 15 minutes without any delays. After that, it introduces a delay of 500ms for each additional request. This approach helps prevent server overload while still allowing some level of access.
By integrating express-rate-limit and express-slow-down into your Node.js application, you can effectively manage the flow of requests, protecting your server from abuse and ensuring a smoother experience for legitimate users. These tools offer a flexible approach to handling high traffic and can be customized to meet the specific needs of your application.