Secure Your Express API — Helmet, Rate Limiting & Validation

🔐 Why API Security is Non-Negotiable in 2025
The internet is a minefield—especially if you’re shipping production APIs. With rising threats like XSS, brute force attacks, and data poisoning, security must be part of your Express.js foundation, not an afterthought.
In this post, I’ll show how I secure every Express API I build using 3 key tools:
Helmet for headers
Express-rate-limit for throttling
Joi / Zod for validation
🛡️ 1. Helmet: Secure HTTP Headers Made Simple
Helmet sets HTTP headers that protect your app from common attacks (like XSS, clickjacking, etc.)
Installation:
npm install helmet
Usage:
const helmet = require("helmet");
app.use(helmet());
Why it matters:
Sets
X-Frame-Options
to avoid clickjackingConfigures
Content-Security-Policy
Blocks sniffing via
X-Content-Type-Options
You can customize the headers:
app.use(helmet({ contentSecurityPolicy: false }));
⚠️ 2. Rate Limiting: Stop Brute Force Attacks
To avoid abuse, throttle the number of requests an IP can make in a time window.
Installation:
npm install express-rate-limit
Usage:
Pro Tip: Use different limits for /auth
routes (e.g. 5 requests/min).
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests
});
app.use("/api/", limiter);
✅ 3. Validate Everything (with Joi or Zod)
Never trust user input. Validate both body and query params.
Example using Joi:
npm install joi
const Joi = require("joi");
const userSchema = Joi.object({
name: Joi.string().min(3).required(),
email: Joi.string().email().required(),
});
app.post("/register", (req, res) => {
const { error } = userSchema.validate(req.body);
if (error) return res.status(400).send(error.details[0].message);
// Proceed safely
});
Zod Alternative (for TS users):
import { z } from "zod";
const loginSchema = z.object({
email: z.string().email(),
password: z.string().min(6),
});
✅ Works great with TypeScript + cleaner syntax!
🧪 Real-World Example: "Expense Tracker API"
I launched an expense tracker API that was open to the public. Within 2 weeks:
Helmet blocked several XSS attempts
Rate limiter stopped an IP making 10,000+ auth requests
Validation prevented MongoDB injection in filters
With just 20 extra lines of code, I avoided chaos.
🧠 Final Thoughts
Security isn’t flashy—it’s foundational. These three tools (Helmet, rate limiting, validation) are my baseline for any public Express API. They protect your server, your users, and your peace of mind.
💬 What other Express security practices do you use? Let’s learn from each other in the comments.
Subscribe to my newsletter
Read articles from Workspace Ronnie directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
