How to optimize Express.js application performance?
Express.js Performance Optimization
Optimizing Express.js involves reducing response times, handling more concurrent requests, and using resources efficiently.
1. Enable Compression
js
const compression = require('compression');
app.use(compression({
level: 6,
threshold: 1024,
filter: (req, res) => {
if (req.headers['x-no-compression']) return false;
return compression.filter(req, res);
}
}));Reduces response size by 60-80% for JSON and text.
2. Use Reverse Proxy (Nginx)
nginx
upstream nodejs {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
keepalive 64;
}
server {
listen 80;
# Serve static files directly
location /static/ {
root /var/www/public;
expires 30d;
add_header Cache-Control "public, immutable";
}
location / {
proxy_pass http://nodejs;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}3. Set NODE_ENV=production
bash
NODE_ENV=production node server.jsExpress caches view templates and generates less verbose error messages in production mode. Many packages also optimize behavior.
4. Database Query Optimization
js
// ❌ N+1 problem
const users = await User.findAll();
for (const user of users) {
user.posts = await Post.findAll({ where: { userId: user.id } });
}
// ✅ Eager loading
const users = await User.findAll({
include: [{ model: Post }]
});
// ✅ Use indexes
// CREATE INDEX idx_posts_user_id ON posts(user_id);5. Async/Await Best Practices
js
// ❌ Sequential — slow
const users = await getUsers();
const products = await getProducts();
const orders = await getOrders();
// ✅ Parallel — fast
const [users, products, orders] = await Promise.all([
getUsers(),
getProducts(),
getOrders()
]);6. Use Streaming for Large Responses
js
app.get('/api/export', async (req, res) => {
res.setHeader('Content-Type', 'application/json');
res.write('[');
const cursor = db.collection('records').find().stream();
let first = true;
cursor.on('data', (doc) => {
if (!first) res.write(',');
res.write(JSON.stringify(doc));
first = false;
});
cursor.on('end', () => {
res.write(']');
res.end();
});
});7. Connection Pooling
js
const pool = new Pool({
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000
});8. Use Cluster Mode
js
const cluster = require('cluster');
const os = require('os');
if (cluster.isPrimary) {
const cpuCount = os.cpus().length;
for (let i = 0; i < cpuCount; i++) {
cluster.fork();
}
cluster.on('exit', (worker) => {
console.log(`Worker ${worker.process.pid} died, restarting...`);
cluster.fork();
});
} else {
const app = require('./app');
app.listen(3000);
}Performance Checklist
| Optimization | Impact | Difficulty |
|---|---|---|
compression middleware | High | Easy |
NODE_ENV=production | Medium | Trivial |
| Reverse proxy (Nginx) | High | Medium |
| Database indexes | Very High | Medium |
| Connection pooling | High | Easy |
| Caching (Redis) | Very High | Medium |
| Cluster mode / PM2 | High | Easy |
Promise.all for parallel | Medium | Easy |
| Stream large data | Medium | Medium |
| Avoid sync operations | High | Easy |
| Use CDN for static files | High | Easy |
Key takeaway: Most Express performance issues come from database queries, not Express itself. Optimize queries first (indexes, eager loading, caching), then infrastructure (Nginx, cluster, compression).
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.