Topics in this subject
Node.js 3 min read Updated 11 Aug 2026

Security and Gotchas

Implementing Helmet, CORS, Rate limiting, and avoiding common Express antipatterns.

🧑‍🏫 Sabse pehle — simple mein samjho#

Server bana kar live karna kaafi nahi hai. Internet pe bohot se bots aur hackers hote hain jo tumhare server pe ddos (lakhon fake requests bhej kar crash karna) attack kar sakte hain ya HTTP headers ke through exploit nikal sakte hain. Express default roop mein itna secure nahi aata, isliye humein security middleware (Helmet, Rate Limiter) ki shields lagani padti hain.

1. Helmet (HTTP Header Security)#

Express natively sends certain headers (like X-Powered-By: Express) that tell hackers exactly what technology stack you are using. Helmet is a collection of 15 smaller middleware functions that set HTTP response headers to protect against common web vulnerabilities (like XSS, clickjacking).

const helmet = require('helmet');

// Add this at the very top of your middleware stack
app.use(helmet()); 

2. Rate Limiting (Preventing Brute Force / DDoS)#

If you have a login endpoint, a hacker might run a script attempting thousands of passwords per second. Rate limiting restricts how many requests a single IP address can make within a specific timeframe.

const rateLimit = require('express-rate-limit');

// Define the limit
const apiLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes timeframe
    max: 100, // Limit each IP to 100 requests per `windowMs`
    message: "Too many requests from this IP, please try again later."
});

// Apply it globally or to specific routes like login
app.use('/api/', apiLimiter);

3. CORS (Cross-Origin Resource Sharing)#

By default, modern browsers block frontend applications (e.g., React on localhost:5173) from making API calls to a backend running on a different port/domain (e.g., localhost:3000). This is a browser security feature. You must explicitly allow the frontend's origin on the backend.

const cors = require('cors');

// Allow all origins (Okay for public APIs, BAD for private apps)
app.use(cors()); 

// Restrict to specific origins (Best Practice)
app.use(cors({
    origin: ['https://my-frontend.com', 'http://localhost:5173'],
    credentials: true // Allow cookies to be sent along with the request
}));

Common Node.js Gotchas / Antipatterns#

1. Blocking the Event Loop ❌#

Never run heavy synchronous operations (like massive for-loops or synchronous cryptographic hashing) on the main thread. It halts all other incoming HTTP requests. If you must process heavy math, use Node's worker_threads to offload the work.

2. Forgetting to return after res.send()#

Express allows execution to continue even after you send a response. If you don't return, you might hit another res.send() later, crashing the app with an ERR_HTTP_HEADERS_SENT error.

app.get('/', (req, res) => {
    if (!req.user) {
        res.status(401).json({ error: "Unauthorized" });
        // execution continues down...
    }
    // ...and hits this! CRASH!
    res.json({ data: "Secret" }); 
});

// Fix: Always use `return res.status(401)...`

3. Not handling Unhandled Rejections ❌#

If a Promise fails somewhere outside of an Express route and there is no .catch() block, Node.js will abruptly crash.

// Add this to the bottom of your server.js to gracefully log these errors
process.on('unhandledRejection', (err, promise) => {
    console.error(`Unhandled Rejection: ${err.message}`);
    // Optionally close the server and exit gracefully
});