Performance Optimization: Caching, Compression, and Database Indexing
API caching, Redis caching, cache invalidation, ETags, compression, gzip, database indexing, query optimization, connection pooling
Performance Optimization: Caching, Compression, and Database Indexing
A REST API that is correct but slow is not production-ready. Performance optimization is a systematic discipline: measure, identify bottlenecks, fix them, and measure again. This lesson covers the most impactful optimizations for REST API performance.
Response Compression
npm install compression
app.use(compression());Gzip compression reduces response sizes by 60-80% with minimal CPU cost. This single line of middleware dramatically reduces bandwidth usage and improves API response times for large payloads.
Redis Response Caching
const cache = (ttlSeconds) => async (req, res, next) => {
const key = `cache:${req.originalUrl}`;
const cached = await redisClient.get(key);
if (cached) {
return res.json(JSON.parse(cached));
}
res.sendResponse = res.json.bind(res);
res.json = (body) => {
redisClient.setex(key, ttlSeconds, JSON.stringify(body));
res.sendResponse(body);
};
next();
};
router.get('/products', cache(300), getAllProducts);Database Indexing
Missing indexes are the most common cause of slow API responses. Add indexes on fields used in queries, sorts, and filters:
userSchema.index({ email: 1 }, { unique: true });
userSchema.index({ role: 1, createdAt: -1 });
userSchema.index({ name: 'text', bio: 'text' });Use MongoDB's explain() to analyze query plans and identify full collection scans. Every field used in a find() filter or sort() should have an index on large collections.
Connection Pooling
Mongoose maintains connection pools — a set of pre-established database connections that requests can reuse. Configure the pool size based on your database server's connection limit and expected concurrency: mongoose.connect(uri, { maxPoolSize: 10 }).
