Assist_Design/docs/CACHING_STRATEGY.md
barsa 2611e63cfd Enhance caching and response handling in catalog and subscriptions controllers
- Added Cache-Control headers to various endpoints in CatalogController and SubscriptionsController to improve caching behavior and reduce server load.
- Updated response structures to ensure consistent caching strategies across different API endpoints.
- Improved overall performance by implementing throttling and caching mechanisms for better request management.
2025-10-29 13:29:28 +09:00

219 lines
6.3 KiB
Markdown

# 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" && <ReactQueryDevtools />}
```
**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)