# CDC Event Flow: Customer-Specific vs Global Cache ## 🎯 The Key Misunderstanding ### What CDC Events Actually Contain ```json // CDC Event from Salesforce { "payload": { "Id": "01t5g000002AbcdEAC", // Product ID "Name": "Internet Home 1G", // Product Name "changeType": "UPDATE", "changedFields": ["Name", "UnitPrice"], "entityName": "Product2" }, "replayId": 12345 } ``` **Notice:** - ✅ Contains: Product ID, what changed - ❌ Does NOT contain: Customer ID, User ID, Account ID - ❌ Does NOT specify: "For Customer A" or "For Customer B" **CDC events are GLOBAL notifications, not customer-specific!** --- ## 🔄 Complete Flow: What Happens With CDC ### Scenario: Price Change for "Internet Home 1G" ``` TIME: 10:00 AM SALESFORCE: Admin changes price $50 → $60 ↓ ↓ (1 CDC Event sent) ↓ PORTAL CDC SUBSCRIBER receives event: { "Id": "01t123...", "changeType": "UPDATE", "changedFields": ["UnitPrice"] } ↓ CACHE INVALIDATION (Global): Redis: DELETE "catalog:internet:plans" ↓ Cache key deleted from Redis No cache exists anymore for ANYONE ``` --- ## 👥 What Happens to Different Customer Types? ### Customer A: Online & Active (viewing website) ``` 10:00:00 AM - Viewing catalog page ↓ Cache hit (old price $50) 10:00:05 AM - CDC event received ↓ Cache deleted 10:00:10 AM - Refreshes page ↓ Cache miss (key deleted) ↓ API call to Salesforce ↓ Fetches new data (price $60) ↓ Stores in cache with 24h TTL ↓ Shows new price $60 ✅ ``` **Action taken:** Cache miss → API call → Fresh data --- ### Customer B: Online & Idle (logged in but not viewing catalog) ``` 10:00:00 AM - Logged in, viewing dashboard (Not looking at catalog) 10:00:05 AM - CDC event received ↓ Cache deleted (global) 10:30:00 AM - Clicks "View Plans" for first time ↓ Cache miss (was deleted at 10:00) ↓ API call to Salesforce ↓ Fetches new data (price $60) ↓ Stores in cache ↓ Shows new price $60 ✅ ``` **Action taken:** Cache miss → API call → Fresh data --- ### Customer C: Offline (not logged in for 7 days) ``` Day 1 - 9:00 AM - Customer C logs in ↓ Cache miss ↓ API call (fetches old price $50) ↓ Cache populated Day 1 - 10:00 AM - CDC event (price changed to $60) ↓ Cache deleted ↓ Customer C logs out Day 2-7: - Customer C offline - Cache doesn't exist (deleted on Day 1) - No action needed ✅ Day 8 - 8:00 AM - Customer C logs back in ↓ Clicks "View Plans" ↓ Cache miss (doesn't exist) ↓ API call to Salesforce ↓ Fetches new data (price $60) ↓ Shows new price $60 ✅ ``` **Action taken:** Nothing during offline period. Fresh fetch on login. --- ## 🎯 Key Point: ONE Cache Key for ALL Customers Your catalog cache structure: ```typescript // GLOBAL cache keys (shared by ALL customers) "catalog:internet:plans" // ← All customers use this "catalog:sim:plans" // ← All customers use this "catalog:vpn:plans" // ← All customers use this // USER-SPECIFIC cache keys (per customer) "catalog:eligibility:801xxx" // ← Customer A's eligibility "catalog:eligibility:802xxx" // ← Customer B's eligibility ``` When Product2 CDC event arrives: ```typescript // Invalidates GLOBAL keys (affects everyone) await cache.delPattern("catalog:internet:*"); await cache.delPattern("catalog:sim:*"); await cache.delPattern("catalog:vpn:*"); // Does NOT invalidate user-specific keys // "catalog:eligibility:801xxx" stays intact ``` --- ## 💡 Why This Works Perfectly ### 1. Offline Customers Don't Waste Resources ✅ ``` CDC event arrives → Cache deleted ↓ Offline customers: - Not requesting data (they're offline) - Not using API calls (they're offline) - Not consuming memory (cache deleted) ↓ Result: ZERO resources wasted ✅ ``` ### 2. Online Customers Get Fresh Data ✅ ``` CDC event arrives → Cache deleted ↓ Next request (from ANY online customer): - Cache miss - 1 API call to Salesforce - Fresh data stored in cache ↓ Subsequent requests (from ALL online customers): - Cache hit - 0 API calls ↓ Result: Fresh data shared by everyone ✅ ``` ### 3. Memory Stays Lean ✅ ``` Before CDC: Redis: "catalog:internet:plans" = [old data] Memory: ~500KB CDC event arrives: Redis: DELETE "catalog:internet:plans" Memory: 0 KB ✅ Next customer request: Redis: "catalog:internet:plans" = [fresh data] Memory: ~500KB (with 24h TTL) ``` --- ## 🔄 Complete Example: 100 Customers ``` SETUP: - 100 total customers - 50 online & active (viewing website) - 30 online & idle (logged in, not viewing catalog) - 20 offline (not logged in) TIME: 10:00 AM - Product price changes in Salesforce ↓ ONE CDC event sent (not 100 events!) ↓ Portal receives event ↓ DELETE "catalog:internet:plans" (one global key) ↓ Cache no longer exists for ANYONE TIME: 10:01 AM - Customer #37 (online, active) refreshes page ↓ Cache miss (key deleted) ↓ 1 API call to Salesforce ↓ Fetches fresh data (new price) ↓ Stores in Redis with 24h TTL ↓ Key: "catalog:internet:plans" = [fresh data] TIME: 10:02 AM - Customer #42 (online, active) refreshes page ↓ Cache HIT (Customer #37 populated it) ↓ 0 API calls ✅ ↓ Shows fresh data TIME: 10:03 AM - Customers #1-20 (online, active) view catalog ↓ All cache HITs ↓ 0 API calls ✅ TIME: 10:30 AM - Customer #55 (was idle, now viewing catalog) ↓ Cache HIT (still fresh from 10:01 AM) ↓ 0 API calls ✅ OFFLINE CUSTOMERS (#81-100): ↓ Not requesting anything (offline) ↓ 0 API calls ✅ ↓ When they log in later: - Cache might exist (if populated by others) - OR Cache might be expired (24h TTL) - Either way: Fresh data RESULT: CDC event: 1 event for 100 customers API calls: 1 call (Customer #37) Cache hits: 99 other customers shared the result Offline customers: 0 impact, 0 waste ``` --- ## 🎯 Direct Answers to Your Questions ### Q1: "We received CDC for a customer that's offline, what do we do?" **Answer:** CDC is NOT "for a customer" - it's a GLOBAL notification! ``` CDC Event: "Product X changed" ↓ Action: Delete global cache key ↓ Offline customer: Does nothing (not requesting data) ↓ When they login later: Fetches fresh data ``` ### Q2: "What do we do for existing customer?" **Answer:** Same action - delete global cache! ``` CDC Event: "Product X changed" ↓ Action: Delete global cache key ↓ Online customer: Next request is cache miss ↓ Fetches fresh data from Salesforce ↓ Stores in cache for everyone ``` --- ## 🔍 Only USER-SPECIFIC Data Has Per-Customer Logic ### Global Cache (CDC invalidates for everyone): ```typescript // Products - same for all customers "catalog:internet:plans" // Prices - same for all customers "catalog:sim:plans" // Addons - same for all customers "catalog:vpn:plans" ``` ### User-Specific Cache (CDC invalidates per customer): ```typescript // Eligibility - different per customer "catalog:eligibility:801xxx" ← Customer A "catalog:eligibility:802xxx" ← Customer B // Orders - different per customer "orders:account:801xxx" ← Customer A's orders "orders:account:802xxx" ← Customer B's orders ``` **Account eligibility CDC:** ```json { "payload": { "AccountId": "801xxx", // ← Specific customer! "Internet_Eligibility__c": "Home 10G" } } ``` **Action:** ```typescript // Only invalidate THAT customer's eligibility await cache.del("catalog:eligibility:801xxx"); // Other customers' eligibility stays cached ✅ ``` --- ## 📊 Summary Table | Cache Type | CDC Event | Offline Customer | Online Customer | |------------|-----------|------------------|-----------------| | **Global Catalog** | Product2 changed | Delete global cache. Customer offline, no impact. When logs in: fresh fetch | Delete global cache. Next request: cache miss, fetch fresh | | **User Eligibility** | Account X changed | Delete cache for Customer X only. Other customers unaffected | Delete cache for Customer X only. Next request: fresh fetch | | **Orders** | Order X changed | Delete cache for Order X & Account. Customer offline, no impact | Delete cache for Order X & Account. Next request: fresh fetch | --- ## 🎓 The Elegance of This Design **Why it works:** 1. **CDC is a notification system**, not a data distribution system 2. **Cache is deleted, not updated** → Zero stale data 3. **Global cache shared by all** → Maximum efficiency 4. **Lazy loading** → Only fetch when actually requested 5. **Offline users invisible** → No special handling needed **Result:** - ✅ Simple logic (no tracking of online/offline) - ✅ Correct behavior (always fresh data) - ✅ Efficient (minimal API calls) - ✅ Memory efficient (deleted cache = 0 bytes) --- ## 🚀 Conclusion **When CDC arrives:** 1. Delete the global cache key 2. Done. That's it. **Offline customers:** - Not requesting data → No impact - No API calls → No cost - No memory used → Efficient **Online customers:** - Next request → Cache miss - 1 API call → Fresh data - Other customers → Cache hit **You don't need to:** - ❌ Track who's online/offline - ❌ Check customer status - ❌ Store data per customer (for global catalog) - ❌ Do anything special **Just:** - ✅ Delete cache when CDC arrives - ✅ Let customers fetch on-demand - ✅ Share cached results globally Simple, correct, efficient! 🎉