This document describes the client-side caching system implemented to reduce Letterboxd API requests and improve Select Friends page performance.
The watchlist cache system implements a multi-layered approach:
- Client-side IndexedDB (primary storage, async)
- localStorage fallback (synchronous access, compatibility)
- Server-side Redis/D1 cache (fallback when client cache unavailable)
- Background conditional fetching (If-None-Match headers, batched updates)
- Maximum entries: 1,000 cached user watchlist counts
- Maximum storage size: 5MB total cache size
- GC threshold: 80% of limits triggers cleanup
- Minimum keep entries: 100 most recent entries always preserved
-
Expired Entry Removal:
- Watchlist counts: 2x refresh window (default: 24 hours)
- Watchlists: 24 hours
- Comparisons: 24 hours
-
Stale Entry Eviction:
- Watchlist counts older than 30 days are removed
- Oldest entries removed first when over storage limits
- Most recently accessed entries always preserved
-
Aggressive Cleanup (when limits exceeded):
- Remove oldest entries beyond minimum threshold
- Prioritize keeping recent and frequently accessed data
- Log cleanup operations for monitoring
- Automatic: On cache write operations when thresholds exceeded
- Manual:
WebCacheService.performGarbageCollection() - Legacy:
WebCacheService.clearExpiredEntries()(deprecated, delegates to GC)
- User opens Select Friends page
- Read cached counts from IndexedDB/localStorage
- Display counts immediately (no loading state)
- Background fetcher schedules conditional checks for stale entries
- Only updated counts trigger new API requests
- No cached data available
- Show loading state while fetching from Letterboxd
- Cache results with timestamp and etag
- Future requests served from cache
When client cache unavailable:
- Server checks Redis/D1 cache
- Respects same refresh window constraints
- Returns cached counts when available
- Falls back to Letterboxd scraping only when necessary
// src/config/watchlistCache.ts
export const WATCHLIST_CACHE_CONFIG = {
ENABLED: true, // Master toggle
REFRESH_WINDOW_HOURS: 12, // How often to check for updates
BACKGROUND_FETCH_BATCH_SIZE: 10, // Batch conditional requests
BACKGROUND_FETCH_DELAY_MS: 2000, // Debounce user interactions
};// Environment variables
FEATURE_CLIENT_WATCHLIST_CACHE = true; // Enable client cache features
FEATURE_SERVER_WATCHLIST_CACHE = true; // Enable server fallback cachecache.hit/cache.miss- Cache effectivenesscache.gc.completed/cache.gc.aggressive- Cleanup operationswatchlist.fetch.conditional- Background updateswatchlist.fetch.changed- Actual changes detected
const stats = WebCacheService.getStorageStats();
// Returns: { entries, sizeMB, limits }- Set
FEATURE_CLIENT_WATCHLIST_CACHE=false - Deploy server changes
- Client falls back to direct Letterboxd requests
- Disable new cache writes:
WATCHLIST_CACHE_CONFIG.ENABLED = false - Allow existing cache to expire naturally
- Monitor for issues before full disable
- Disable all cache features
- Remove
watchlistCachefield from API requests - Revert server endpoints to ignore cache parameters
- Clear client storage:
WebCacheService.clearCache()
src/services/cacheService.ts- Main cache implementationsrc/config/watchlistCache.ts- Configurationsrc/services/watchlistFetcher.ts- Background fetcher
functions/letterboxd/cache/index.ts- Server cache modulefunctions/api/watchlist-count-updates/index.ts- Update notificationsfunctions/letterboxd/friends/index.ts- Select Friends endpoint
src/components/FriendSelectionPage.tsx- Cache-aware renderingsrc/App.tsx- Cache initialization and fetcher startup
- Unit tests: Cache read/write/corruption handling
- Integration tests: Server fallback behavior
- E2E tests: Cache hit/miss flows, change detection
- Performance tests: GC operations, storage limits
src/__tests__/cacheService.test.tssrc/__tests__/cacheService.idb.test.tsfunctions/__tests__/cache.unit.test.tsfunctions/__tests__/friends-cache-integration.test.ts
- Letterboxd request reduction: 80-95% for repeat Select Friends usage
- Page load improvement: Instant display of cached counts
- Storage efficiency: Automatic cleanup maintains <5MB storage
- Background updates: Non-blocking conditional checks
- Cache hit rate: >80% for active users
- Storage usage: <4MB average, <5MB maximum
- GC frequency: <1 aggressive cleanup per day per user
- Background fetch success: >95% conditional request efficiency
Last Updated: 2025-01-02 Version: 1.0.0 Status: Production Ready