How Caching Works
The caching system stores generated wrapped data for 24 hours, allowing subsequent requests for the same repository and year to be served instantly without hitting the GitHub API.Cache Flow
Cache hit or miss
- Cache HIT: Return cached data immediately (0 API calls, under 100ms response)
- Cache MISS: Fetch from GitHub API, store in cache, return data
Dual-Layer Caching Architecture
GitHub Wrapped uses a dual-layer approach that works in all environments:Layer 1: In-Memory Cache (Default)
Works out-of-the-box with zero configuration:- No external dependencies required
- Extremely fast (nanosecond access)
- Persists only during server runtime
- Perfect for single-instance deployments
- Lost on server restart
Layer 2: Redis Cache (Optional)
For production deployments with multiple instances:- Shared across all instances
- Persists across server restarts
- Ideal for serverless deployments (Vercel, AWS Lambda)
- Requires Upstash Redis configuration
The system automatically uses Redis if configured, falling back to in-memory cache otherwise. You don’t need to change any code.
Cache Types
GitHub Wrapped caches three types of data:1. Wrapped Data Cache
Stores complete wrapped visualizations:wrapped:facebook/react/2024wrapped:vercel/next.js/2023
2. Validation Cache
Stores repository validation results to avoid repeated validation calls:validate:facebook/reactvalidate:microsoft/vscode
3. Custom Wrapped Cache
Stores wrappeds with custom date ranges:wrapped:facebook/react/2024-q1wrapped:vercel/next.js/custom-range
Setting Up Redis Caching
For production deployments, configure Redis for distributed caching:Create an Upstash Redis database
- Sign up at upstash.com
- Create a new Redis database
- Choose a region close to your deployment
Redis Configuration Code
The Redis client is initialized inlib/redis.ts:
Cache Operations
Reading from Cache
Writing to Cache
Clearing Cache
Manually invalidate cache for a specific repository:Cache TTL (Time-To-Live)
All cached data expires after 24 hours:Why 24 Hours?
- Fresh data: Repository data changes frequently
- API efficiency: Balances freshness with API call reduction
- User expectations: Users expect relatively current data
- Rate limits: Prevents rate limit exhaustion for popular repos
For historical data (e.g., “2023 wrapped” in 2024), a longer TTL could be beneficial. Consider customizing TTL for past years.
Cache Performance Impact
Without Cache
- API calls: 10-40 per request
- Response time: 3-10 seconds
- Rate limit impact: High (could exhaust limits quickly)
With Cache (Cache Hit)
- API calls: 0
- Response time: Under 100ms
- Rate limit impact: None
Performance Example
For a popular repository with 100 requests per day:| Metric | Without Cache | With Cache |
|---|---|---|
| API calls/day | 1,000-4,000 | 20-80 (only first request) |
| Avg response time | 5s | 0.05s |
| Rate limit usage | 20-80% of daily quota | Under 2% |
| Cache hit rate | 0% | 99% |
Cache Expiration Logic
The cache includes automatic expiration checking:Expiration Handling
Advanced Caching Patterns
Warming the Cache
Pre-populate cache for popular repositories:Cache Hit Rate Monitoring
Track cache effectiveness:Selective Cache Invalidation
Invalidate cache when repository data significantly changes:Caching Best Practices
For Small Deployments
- Use in-memory cache (default)
- No configuration needed
- Perfect for personal instances
- Single server deployments
For Production
- Configure Redis caching
- Use Upstash for serverless
- Monitor cache hit rates
- Consider cache warming for popular repos
Optimization Tips
- Enable Redis for serverless: Essential for Vercel, AWS Lambda, etc.
- Monitor TTL effectiveness: Adjust based on your use case
- Implement cache warming: Pre-populate for popular repositories
- Track hit rates: Optimize caching strategy based on metrics
- Consider longer TTL for historical data: Past years rarely change
Troubleshooting
Cache not persisting across requests
Cache not persisting across requests
Problem: Each request seems to miss the cacheSolutions:
- Check if Redis is properly configured (for serverless)
- Verify
UPSTASH_REDIS_REST_URLandUPSTASH_REDIS_REST_TOKEN - In-memory cache doesn’t work across multiple serverless instances
Stale data being served
Stale data being served
Problem: Data not updating after 24 hoursSolutions:
- Check if cache expiration is working: verify
Date.now() > entry.expiresAt - Manually clear cache:
await clearCache(owner, repo, year) - Verify system clock is accurate
Redis connection errors
Redis connection errors
Problem: Errors connecting to Upstash RedisSolutions:
- Verify credentials are correct
- Check network connectivity to Upstash
- Ensure Redis instance is in the same region (lower latency)
- App falls back to in-memory cache on Redis errors
High memory usage
High memory usage
Problem: In-memory cache consuming too much memorySolutions:
- Switch to Redis for large-scale deployments
- Implement cache size limits (not currently in code)
- Use Redis for distributed caching
Cache Monitoring
Monitor cache effectiveness in production:Next Steps
- Set up Redis caching for production
- Learn about rate limits and how caching helps
- Configure environment variables
- Complete the setup guide