Caching Strategy
Related docs:
Hosting Infrastructure·SDLC/DESIGN·Microservices
1. Redis Deployment
Redis runs as a system service on the same EC2 instance as the core services, accessible only within the VPC (port 6379 blocked at security group level for external traffic).
Connection string:
REDIS_URL=redis://localhost:6379
Recommended production configuration (/etc/redis/redis.conf):
maxmemory 2gb
maxmemory-policy allkeys-lru
save "" # Disable RDB persistence (ephemeral by design)
appendonly no # Disable AOF (data reconstructable from DB)
requirepass your_password # Enable auth in production
1.1 Redis Database Allocation
| DB | Purpose | Services |
|---|---|---|
| 0 | Production sessions, carts, rate limiting, general cache | All production services |
| 1 | Test environment (CI, local dev) | Test suites |
| 2 | BullMQ job queues | scheduler, backend, notifications |
| 3 | Tracking pub/sub channels | tracking service |
| 4 | Recommendations cache | recommendations service |
| 5 | Feature flags cache | config service |
| 6 | Analytics cache | analytics service |
| 7 | Fraud detection cache | fraud service |
2. Use Cases and Key Conventions
2.1 User Sessions
Sessions are stored in Redis using a JWT reference map (not the full JWT payload).
| Key pattern | session:{sessionId} |
|---|---|
| Value | { userId, role, expiresAt } (JSON) |
| TTL | 7 days (rolling; refreshed on each authenticated request) |
| Invalidation | DEL session:{sessionId} on logout; KEYS session:* scan on global logout |
2.2 Cart Data
Cart contents are persisted in Redis for guest and authenticated users alike.
| Key pattern | cart:{userId} or cart:guest:{fingerprint} |
|---|---|
| Value | { items: [...], updatedAt } (JSON) |
| TTL | 30 days |
| Invalidation | On order placement (clearCart()) or manual cart clear |
Migration: On login, any guest cart (cart:guest:*) is merged into the authenticated cart and the guest key deleted.
2.3 Rate Limiting
Express API uses a Redis-backed sliding-window rate limiter.
| Key pattern | ratelimit:{ip}:{endpoint} |
|---|---|
| Value | Request count (integer) |
| TTL | 15 minutes |
| Limit | 1,000 requests / 15 min (general); 20 requests / 15 min (payment initiation); 20 requests / 15 min (auth) |
Payment endpoints have a stricter limit to prevent brute-force USSD spam.
2.4 Temporary Payment Status Cache
After a webhook updates an order's payment status, the result is cached briefly to reduce DB polling pressure.
| Key pattern | payment_status:{orderId} |
|---|---|
| Value | { paymentStatus, updatedAt } (JSON) |
| TTL | 60 seconds |
| Invalidation | Auto-expiry; webhook handler sets the key after each update |
The GET /api/v1/payments/status/:orderId endpoint reads from this cache first, falling back to the database.
2.5 Product Listing Cache
Frequently accessed product listing pages are cached to reduce DB load.
| Key pattern | products:{queryHash} |
|---|---|
| Value | Serialised product list + pagination (JSON) |
| TTL | 5 minutes |
| Invalidation | DEL products:* on product create/update/delete (via a cache invalidation hook in the product service) |
2.6 Search Cache
Meilisearch results are cached for popular queries.
| Key pattern | search:{queryHash} |
|---|---|
| Value | Serialised search results (JSON) |
| TTL | 2 minutes |
| Invalidation | Auto-expiry; product index updates trigger selective invalidation |
2.7 Feature Flags Cache
Feature flags from the config service are cached in Redis for fast access.
| Key pattern | feature_flags:{flagKey} |
|---|---|
| Value | Boolean or JSON configuration |
| TTL | 1 hour |
| Invalidation | Admin toggles flag → config service invalidates all feature_flags:* keys |
2.8 Fraud Detection Cache
Temporary fraud scoring data is cached to enable velocity checks.
| Key pattern | fraud:velocity:{ip}:{hourBucket} |
|---|---|
| Value | { paymentCount, amountTotal, lastPaymentAt } (JSON) |
| TTL | 1 hour |
| Invalidation | Auto-expiry |
| Key pattern | fraud:risk_score:{userId} |
|---|---|
| Value | { score, calculatedAt, factors: [...] } (JSON) |
| TTL | 24 hours |
| Invalidation | New payment triggers recalculation |
2.9 Tracking Location Cache
Latest agent location is cached for fast retrieval.
| Key pattern | tracking:location:{orderId} |
|---|---|
| Value | { lat, lng, accuracy, timestamp, speed, heading } (JSON) |
| TTL | 5 minutes |
| Invalidation | Auto-expiry; new location update overwrites |
2.10 Analytics Cache
Pre-aggregated analytics data for dashboards.
| Key pattern | analytics:{metric}:{granularity}:{date} |
|---|---|
| Value | Aggregated metric data (JSON) |
| TTL | 1 hour (hourly), 24 hours (daily), 7 days (weekly) |
| Invalidation | Auto-expiry; new data triggers background recalculation |
3. Key Naming Summary
| Prefix | Use case | TTL | DB |
|---|---|---|---|
session:{id} | User session | 7 days | 0 |
cart:{userId} | Authenticated cart | 30 days | 0 |
cart:guest:{fp} | Guest cart | 30 days | 0 |
ratelimit:{ip}:{ep} | Rate limiting | 15 min | 0 |
payment_status:{orderId} | Payment status cache | 60 sec | 0 |
products:{hash} | Product listing cache | 5 min | 0 |
search:{hash} | Search results cache | 2 min | 0 |
feature_flags:{key} | Feature flags | 1 hour | 5 |
fraud:velocity:{ip} | Fraud velocity tracking | 1 hour | 7 |
fraud:risk_score:{userId} | Fraud risk score | 24 hours | 7 |
tracking:location:{orderId} | Agent location | 5 min | 3 |
analytics:{metric} | Analytics aggregates | 1h-7d | 6 |
bullmq:{queue} | Job queue metadata | Varies | 2 |
recommendations:{userId} | Product recommendations | 1 hour | 4 |
4. Cache Invalidation Rules
| Event | Cache keys invalidated |
|---|---|
| User logout | session:{sessionId} |
| Order placed | cart:{userId}, payment_status:{orderId} |
| Product created / updated / deleted | products:*, search:*, recommendations:* |
| Webhook updates payment status | payment_status:{orderId} (overwritten, not deleted) |
| Admin clears all sessions | session:* (scan + delete) |
| Feature flag toggled | feature_flags:* |
| Fraud rule updated | fraud:risk_score:* |
| New tracking location | tracking:location:{orderId} (overwritten) |
| Settlement completed | analytics:settlements:* |
5. Pub/Sub Channels
5.1 Tracking Channels
| Channel | Publisher | Subscribers | Purpose |
|---|---|---|---|
order:{orderId}:location | tracking service | WebSocket clients | Live location updates |
order:{orderId}:status | backend | WebSocket clients | Order status changes |
order:{orderId}:arriving | tracking service | notification service | Geofence trigger |
5.2 Notification Channels
| Channel | Publisher | Subscribers | Purpose |
|---|---|---|---|
user:{userId}:notifications | notifications service | SSE clients | Real-time in-app notifications |
broadcast:all | admin dashboard | All SSE clients | Platform-wide announcements |
6. Observability
All Redis operations are traced via Middleware.io OpenTelemetry instrumentation. Cache hit/miss ratios are visible in the Middleware.io dashboard under the redis span group.
Alert thresholds:
| Metric | Threshold | Action |
|---|---|---|
| Cache memory > 80% | Alert | Risk of eviction; review TTLs or scale Redis |
| Redis connection errors > 5/min | Critical | Investigate network or Redis health |
| Cache hit rate < 70% | Warning | Review cache key design or TTL values |
| Pub/Sub message lag > 5s | Warning | Check subscriber health |
For internal use only. Do not distribute outside Pakashop engineering.