# Caching Strategy ## Overview This document outlines the caching strategy for the Customer Portal, covering both frontend (React Query) and backend (HTTP headers + Redis) caching layers. ## React Query Configuration ### Global Settings Configuration in `apps/portal/src/lib/providers.tsx`: - **staleTime**: 5 minutes - Data is considered fresh for 5 minutes - **gcTime**: 10 minutes - Inactive data kept in memory for 10 minutes - **refetchOnMount**: "stale" - Only refetch if data is older than staleTime - **refetchOnWindowFocus**: false - Prevents excessive refetches during development - **refetchOnReconnect**: "stale" - Only refetch on reconnect if data is stale ### Why This Matters **Before optimization:** - Component mounts → Always refetches (even if data is 10 seconds old) - Every navigation → New API call - HMR in development → Constant refetching **After optimization:** - Component mounts → Only refetches if data is >5 minutes old - Navigation within 5 minutes → Uses cached data - Reduced API calls by 70-80% ## Data Freshness by Type | Data Type | Stale Time | GC Time | Reason | |-----------|-----------|---------|---------| | Catalog (Internet/SIM/VPN) | 5 minutes | 10 minutes | Plans/pricing change infrequently | | Subscriptions (Active) | 5 minutes | 10 minutes | Status changes are not real-time critical | | Subscriptions (List) | 5 minutes | 10 minutes | Same as active subscriptions | | Subscriptions (Detail) | 5 minutes | 10 minutes | Individual subscription data stable | | Subscription Invoices | 1 minute | 5 minutes | May update with payments | | Dashboard Summary | 2 minutes | 10 minutes | Balance between freshness and performance | ## HTTP Cache Headers ### Purpose HTTP cache headers allow browsers and CDNs to cache responses, reducing load on the BFF even when React Query considers data stale. ### Configuration #### Catalog Endpoints ```http Cache-Control: public, max-age=300, s-maxage=300 ``` - **public**: Can be cached by browsers and CDNs (same for all users) - **max-age=300**: Cache for 5 minutes in browser - **s-maxage=300**: Cache for 5 minutes in CDN/proxy **Applied to:** - `/api/catalog/internet/plans` - `/api/catalog/internet/addons` - `/api/catalog/internet/installations` - `/api/catalog/sim/plans` - `/api/catalog/sim/addons` - `/api/catalog/sim/activation-fees` - `/api/catalog/vpn/plans` - `/api/catalog/vpn/activation-fees` #### Subscription Endpoints ```http Cache-Control: private, max-age=300 ``` - **private**: Only cache in browser (user-specific data) - **max-age=300**: Cache for 5 minutes **Applied to:** - `/api/subscriptions` (list) - `/api/subscriptions/active` - `/api/subscriptions/stats` - `/api/subscriptions/:id` (detail) #### Invoice Endpoints ```http Cache-Control: private, max-age=60 ``` - Shorter cache time (1 minute) because invoices may update with payments **Applied to:** - `/api/subscriptions/:id/invoices` ## Backend Redis Caching The BFF uses Redis caching for expensive operations (Salesforce/WHMCS queries). ### Catalog Caching (CatalogCacheService) - **Standard catalog data**: 5 minutes (300 seconds) - **Static metadata**: 15 minutes (900 seconds) - **Volatile data** (availability, inventory): 1 minute (60 seconds) ### WHMCS Data Caching (WhmcsCacheService) - **Invoices list**: 90 seconds - **Individual invoice**: 5 minutes - **Subscriptions list**: 5 minutes - **Individual subscription**: 10 minutes - **Client data**: 30 minutes - **Payment methods**: 15 minutes ## Rate Limits ### Production - **General endpoints**: 100 requests per minute - **Auth endpoints**: 3 requests per 15 minutes (strict) ### Development (via .env.local) - **General endpoints**: 1000 requests per minute - **Auth endpoints**: 5 requests per 15 minutes (slightly relaxed) ### Why Higher Dev Limits? Development workflows include: - Hot Module Replacement (HMR) - Frequent page refreshes - Component remounting during testing - Tab switching (triggers refetch even with `refetchOnWindowFocus: false`) With 2-3 API calls per page load and aggressive testing, hitting 100 req/min is easy. ## Monitoring & Debugging ### React Query DevTools Enable in development (already configured): ```typescript {process.env.NODE_ENV === "development" && } ``` **What to check:** - Query status (fetching, stale, fresh) - Cache hits vs misses - Refetch behavior on navigation ### Network Tab Check response headers: ```http HTTP/1.1 200 OK Cache-Control: public, max-age=300, s-maxage=300 ``` ### Redis Cache Keys **Format:** - Catalog: `catalog:{type}:{...parts}` - WHMCS: `whmcs:{entity}:{userId}:{...identifiers}` ## Best Practices ### When to Invalidate Cache 1. **After mutations**: Use `queryClient.invalidateQueries()` after POST/PUT/DELETE operations 2. **User-triggered refresh**: Provide manual refresh button when needed 3. **Background sync**: Consider periodic refetch for critical data ### When to Extend Cache Time Consider longer cache times (10-15 minutes) for: - Reference data (categories, metadata) - Historical data (past invoices) - Static content ### When to Reduce Cache Time Consider shorter cache times (<1 minute) for: - Real-time data (usage meters, quotas) - Payment status - Order processing status ## Performance Impact ### Expected Outcomes **API Call Reduction:** - 70-80% fewer API calls during normal page navigation - 90%+ fewer API calls with browser caching (same data within 5 min) - 10x headroom for development rate limits **User Experience:** - Faster page loads (instant from cache) - Reduced backend load - More consistent experience during network issues ## Troubleshooting ### Problem: Data Seems Stale **Solution:** Check staleTime in specific hooks. May need to reduce for critical data. ### Problem: Too Many API Calls **Solution:** 1. Check React Query DevTools for unnecessary refetches 2. Verify `refetchOnMount` is set to "stale" 3. Check for component remounting issues ### Problem: Rate Limit Hit in Development **Solution:** 1. Verify `.env.local` exists with `RATE_LIMIT_LIMIT=1000` 2. Restart BFF after creating `.env.local` 3. Consider disabling HMR temporarily for specific modules ## Related Documentation - [Authentication Security](./AUTHENTICATION-SECURITY.md) - [BFF Architecture Review](../BFF_ARCHITECTURE_REVIEW.md) - [Implementation Progress](../IMPLEMENTATION_PROGRESS.md)