Building an Express API with Logging and Rate Limiting



This content originally appeared on DEV Community and was authored by Mohammed jobair Hossain

When building an API, two important things often get overlooked by beginners: logging and rate limiting.
In this blog, we’ll explore why they matter, and how to add them to a Node.js Express server.

1. Why Logging Matters

Logging is like your app’s diary — it keeps track of important events, errors, and activity happening in your application.

In production, logs can help you:

  • Debug issues quickly.
  • Track suspicious activity.
  • Monitor server performance.
const { createLogger, format, transports } = require("winston");

const logger = createLogger({
  level: "info",
  format: format.combine(
    format.timestamp(),
    format.printf(({ level, message, timestamp }) => {
      return `${timestamp} [${level.toUpperCase()}]: ${message}`;
    })
  ),
  transports: [
    new transports.Console(),
    new transports.File({ filename: "logs/server.log" })
  ]
});

module.exports = logger;

2. Why Rate Limiting Matters

Rate limiting prevents a single user (or bot) from overwhelming your server with too many requests.

It helps protect against:

  • Brute force attacks
  • DDoS (Distributed Denial-of-Service) attempts
  • Server overload
const rateLimit = require("express-rate-limit");
const logger = require("./logger");

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  limit: 10, // Max 10 requests per IP
  standardHeaders: true,
  legacyHeaders: false,
  handler: (req, res) => {
    logger.info(`Rate limit exceeded for IP: ${req.ip}`);
    res.status(429).send({
      error: "Too many requests, please try again later.",
      rateLimit: {
        limit: 10,
        remaining: 0,
        resetTime: new Date(Date.now() + 15 * 60 * 1000).toISOString()
      }
    });
  }
});

module.exports = limiter;

📌 This allows 10 requests per IP every 15 minutes. When the limit is exceeded, it logs the IP and returns a 429 error.

3. Putting It All Together

We’ll build a small Express server that uses both logging and rate limiting.

const express = require("express");
const limiter = require("./limiter");
const logger = require("./logger");

const app = express();

// Apply rate limiter to all routes
app.use(limiter);

// Basic route
app.get("/", (req, res) => {
  logger.info(`Request to / from IP: ${req.ip}`);
  res.send("Hello, World!");
});

// Start server
const PORT = 3000;
app.listen(PORT, () => {
  logger.info(`Server is running on http://localhost:${PORT}`);
});


This content originally appeared on DEV Community and was authored by Mohammed jobair Hossain