A Node.js application demonstrating defensive caching patterns with Redis. This application shows how to implement fallback caching strategies when external services fail.
- Defensive Caching: Automatically falls back to cached data when external services fail
- Redis Integration: Uses Redis for fast, persistent caching
- Docker
- Docker Compose
-
Start the application:
docker-compose up --build
-
Access the application:
- API: http://localhost:3000
- Health check: http://localhost:3000/health
- Redis: localhost:6379
-
Test Commands
# Test the endpoint multiple times to see caching behavior for i in {1..10}; do echo "Request $i:" curl -s http://localhost:3000/api/recommendations | jq . echo "---" sleep 1 done
src/
├── index.ts # Main application entry point
├── routes/ # API route definitions
│ ├── index.ts # Route aggregator
│ └── recommendation.ts # Recommendation endpoints
├── services/ # Business logic
│ └── list-recommendations.ts # Recommendation service with defensive caching
└── infra/ # Infrastructure layer
└── cache/ # Caching infrastructure
├── cache-provider.ts # Cache abstraction layer
└── redis.ts # Redis client configuration
- GET
/api/recommendations- Get recommendations with defensive caching- Success Response (200): Returns recommendations from external service or cache
- Fallback: Automatically uses cached data if external service fails
- Error Response (500): Only if both external service and cache fail
The application implements a defensive caching pattern:
- Primary: Attempt to fetch data from external service
- Cache on Success: Store successful responses in Redis cache
- Fallback on Failure: If external service fails, return cached data
- Graceful Degradation: Only return error if both sources fail
- Use cases:
- E-commerce recommendations page: we have a page with recommendations that are fetched from an external service, but this service is not always available, so we want to show the recommendations even if the external service fails.
External Service Request → Success → Cache Data → Return Response
↓
Failure → Check Cache → Return Cached Data
↓
No Cache → Return Error
The application includes a simulated external service that randomly fails (50% chance). This allows you to test the defensive caching behavior:
- First Request: May succeed or fail randomly
- Subsequent Requests: If first succeeded, cache will be populated
- Failed Requests: Will automatically fall back to cached data
- Cache Miss: Only returns error if both external service and cache fail
Arlen Vasconcelos