Skip to content

Api Caching Project

DodaTech 2 min read

title: "API Caching Project — Build a Multi-Tier Caching System" description: "Build a production multi-tier caching system with Redis, Nginx reverse proxy, HTTP headers, and CDN configuration for a real API deployment." date: 2026-06-28 lastmod: 2026-06-28 weight: 25 tags: [apis, caching] }

Build a complete multi-tier caching system for an API combining Redis application caching, Nginx reverse proxy, HTTP cache headers, and CDN configuration.

What You'll Learn

  • Implementing a multi-tier cache
  • TTL coordination and cache invalidation
  • Measuring cache performance

Why It Matters

This project combines all caching concepts into a deployable caching layer that improves API response time from 200ms to under 10ms.

Project Structure

# app.py - Complete caching API
from flask import Flask, request, jsonify
import redis, hashlib, json, threading, time
from functools import wraps

app = Flask(__name__)
redis_client = redis.Redis(host='localhost', port=6379, decode_responses=True)

# Cache decorator with multi-tier support
def cache(ttl=300, stale_ttl=600):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            key = f'api:{request.path}:{hashlib.md5(request.query_string).hexdigest()}'

            # Try Redis
            cached = redis_client.get(key)
            if cached:
                response = jsonify(json.loads(cached))
                response.headers['X-Cache-Tier'] = 'redis'
                response.headers['Cache-Control'] = f'public, max-age={min(60, ttl)}'
                return response

            # Compute response
            data = f(*args, **kwargs)
            redis_client.setex(key, ttl, json.dumps(data))

            response = jsonify(data)
            response.headers['X-Cache-Tier'] = 'miss'
            response.headers['Cache-Control'] = f'public, max-age={min(60, ttl)}'
            response.headers['ETag'] = hashlib.sha256(
                json.dumps(data, sort_keys=True).encode()
            ).hexdigest()
            return response
        return wrapper
    return decorator

@app.route('/api/products')
@cache(ttl=300)
def get_products():
    # Simulate DB query
    time.sleep(0.1)
    return [{"id": i, "name": f"Product {i}"} for i in range(100)]
# nginx.conf - Reverse proxy cache layer
http {
    upstream app {
        server localhost:5000;
    }

    proxy_cache_path /var/cache/nginx levels=1:2
                     keys_zone=api_cache:10m
                     max_size=1g
                     inactive=60m;

    server {
        listen 80;
        server_name api.example.com;

        location /api/ {
            proxy_cache api_cache;
            proxy_cache_valid 200 5m;
            proxy_cache_key "$host$request_uri";
            proxy_pass http://app;

            add_header X-Cache-Status $upstream_cache_status;
            add_header X-Cache-Tier "nginx" always;

            # Bypass cache for POST/PUT/DELETE
            proxy_no_cache $request_method;
            proxy_cache_bypass $request_method;
        }
    }
}

Testing and Monitoring

# test_caching.py
def test_cache_performance():
    import requests
    import time

    base = 'http://localhost:5000'

    # First request (cold)
    start = time.time()
    r1 = requests.get(f'{base}/api/products')
    cold_time = time.time() - start
    print(f'Cold request: {cold_time*1000:.1f}ms')

    # Second request (cached)
    start = time.time()
    r2 = requests.get(f'{base}/api/products')
    hot_time = time.time() - start
    print(f'Cached request: {hot_time*1000:.1f}ms')

    # Verify cache headers
    assert 'X-Cache-Tier' in r2.headers
    print(f'Improvement: {cold_time/hot_time:.0f}x faster')

Challenge

Extend the project with:

  1. Cache purging endpoint that invalidates by key pattern
  2. Prometheus metrics for cache hit ratio
  3. Stale-while-revalidate pattern
  4. Distributed cache locking for stampede prevention

FAQ

How do I measure cache hit ratio?

: Track X-Cache-Status or X-Cache-Tier headers in your monitoring.

What is the optimal Redis TTL for APIs?

: 60-300 seconds for most endpoints. Adjust based on data freshness needs.

Should I cache error responses?

: No. Do not cache 4xx or 5xx responses.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro