Script Valley
REST API Development: Complete Course from Beginner to Production
Production and Best Practices: Logging, Monitoring, Documentation, and DeploymentLesson 6.3

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.

DiagramRedis Caching Flow

IMAGE PROMPT (replace this block with your generated image):

Flat cache hit vs cache miss flow diagram on white background. Title: Redis Response Caching — Cache Hit vs Cache Miss. Two parallel flow paths shown side by side. Left path: Cache Hit (Fast Path) — Steps: 1. Client sends GET /products. 2. API checks Redis (Redis box with red R icon). 3. Cache HIT (green checkmark). 4. Return cached JSON instantly. Arrow labeled ~5ms response time (green). Right path: Cache Miss (Slow Path) — Steps: 1. Client sends GET /products. 2. API checks Redis. 3. Cache MISS (red X). 4. Query MongoDB (database cylinder). 5. Store result in Redis with TTL label (e.g. TTL: 300s). 6. Return JSON to client. Arrow labeled ~250ms response time (amber). Between both paths: a badge showing Performance Gain: 50x faster on cache hit. Redis box filled with brand color #3A5EFF. White background, clean numbered steps.

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 }).

Up next

Containerizing REST APIs with Docker

Sign in to track progress