The internet is not polite
Public APIs get bots guessing passwords, oversized bodies, injection attempts and scrapers. A few habits stop most of it: validate every input, limit request rates, set security headers, and never leak internals in errors.
The checklist
- Validate everything from clients (body, params, query, headers) — types, lengths, ranges. Libraries: Zod, Valibot.
- Rate limit login and expensive routes (e.g. 5 login attempts per minute per IP).
- Never build SQL with string concatenation — use parameterised queries or an ORM (Databases course!).
- Security headers with helmet; CORS only for origins you trust.
- Errors: log details on the server; send clients a generic message.
- Dependencies: npm audit and keep packages updated.
import express from "express";
const app = express();
const hits = new Map();
function rateLimit({ windowMs, max }) {
return (req, res, next) => {
const key = req.get("x-client-id") ?? "anon";
const now = Date.now();
const recent = (hits.get(key) ?? []).filter((t) => now - t < windowMs);
recent.push(now);
hits.set(key, recent);
if (recent.length > max) return res.status(429).json({ error: "Too many requests" });
next();
};
}
app.get("/menu", rateLimit({ windowMs: 1000, max: 3 }), (req, res) => res.json(["Momo"]));
app.listen(3000);
for (let i = 1; i <= 5; i++) console.log("request", i, (await fetch("http://localhost:3000/menu")).status);