Performance Patterns with Redis Caching - Slides
Instructor slide content for Unit 5: implementing Cache-Aside, Read-Through, and Write-Through patterns with Redis
SLIDE DECK: MODULE 05 - PERFORMANCE (REDIS CACHING) - V3.0 (FINAL VERSION)
Total Duration: 120 minutes (Concept/Lecture) Audience: Fresher/Employee (Completed Module 04: SAGA)
Slide 1: Title Page
- Content:
- (Company / Training Unit Logo)
- MODULE 06: PERFORMANCE PATTERNS
- Speeding Up the System with Redis Caching
- "Your System is 'Safe' (SAGA), but is it 'Fast'?"
- Trainer: (Your Name)
- Date: (Training Date)
- Visualization:
- Key visual: An [Icon: Turtle] (gray, faded) representing the Database. Next to it, an [Icon: Rocket] (red, sharp) representing Redis.
- The Redis logo is in the corner.
- Instructor Script:
- "Welcome to Module 05. In the previous modules, we mastered the hardest part: making our system 'Safe' and 'Consistent' (with the SAGA Pattern)."
- "But 'Safe' is not enough. Users hate waiting. An API like
GET /productsbeing called 1000 times a second cannot 'ask' the database every single time." - "Today, we solve the performance 'bottleneck.' We will learn how to make our system 10x, 100x 'Faster' by using Caching with Redis, the ultimate weapon for accelerating read performance."
Slide 2: Session Agenda (Updated V3.0)
- Content:
- AGENDA (120 MINUTES)
- P1. The Pain: DB Bottleneck & Caching Concepts (~15 mins)
- P2. The Tool: Intro to Redis & Operations (Eviction, MaxMemory) (~10 mins)
- P3. Strategy: Cache-Aside (Flowchart & "Production" Code-along) (~40 mins)
- P4. "Hard Part" #1: Anti-Cache Stampede (Mutex, Jitter) (~15 mins)
- P5. "Hard Part" #2: Cache Invalidation & Key Design (~20 mins)
- P6. Real-world Case Studies (Timeline, Counter) (~10 mins) [NEW]
- P7. Best Practices Summary & Q&A (~10 mins) [NEW]
- Visualization:
- A 7-step timeline, designed like a processing 'pipeline.' P3 (Code), P4 (Stampede), and P5 (Invalidation) are highlighted (e.g., in orange) as critical 'pressure valves.' P6 (Case Studies) is the 'real-world output.'
- Instructor Script:
- "This is our complete 120-minute agenda. We will move from 'The Pain' (P1) to 'The Tool' (P2) and 'Real-world Code' (P3, P4, P5)."
- "[EMPHASIZE] In P6 (new), we will see how 'giants' like Twitter/Facebook use caching for massive-scale systems."
- "Finally, in P7 (new), we will 'lock in' the 10 golden rules (Best Practices) for operating a cache before the Q&A and assignment."
Slide 3: Learning Objectives (Updated V3.0)
- Content:
- OBJECTIVES (AFTER THIS MODULE, YOU WILL BE ABLE TO...)
- 1. Explain: The benefits of Caching, the Key-Value concept, and
Evictionpolicies. - 2. Implement: The Cache-Aside Pattern (with
asyncandfallbackon Redis failure). - 3. Apply: Anti-Cache Stampede techniques (using
Mutex/SETNXandJitter TTL). - 4. Analyze: Cache Invalidation strategies (TTL, Event-based) and Key Versioning.
- 5. Relate: Describe real-world Case Studies (e.g., Timelines, Counters) that use Redis. [NEW]
- Visualization:
- 5 clear icons: [Icon: Brain (Explain)], [Icon: Gears (Implement)], [Icon: Shield (Apply)], [Icon: Chart (Analyze)], [Icon: Building (Relate)].
- Instructor Script:
- "Our objectives have been upgraded. You won't just 'Implement' (Objective 2) and 'Apply' (Objective 3) production-ready techniques; you must also be able to 'Relate' (Objective 5 - new) these techniques to the real-world case studies we're about to cover."
Slide 4: Module 04 Recap
- Content:
- RECAP: WHERE ARE WE?
- Module 04: We built a "Safe" SAGA Pattern.
Order -> Payment -> Inventory(Happy Path)Inventory (Fail) -> Payment (Refund)(Failure Path)
- The system is now "Consistent."
- NEW PROBLEM: PERFORMANCE
- Our
GET /products/{product_id}API is called 1000 times/second. - All 1000 of those calls are hitting the Database directly.
- Visualization: *
- A diagram:
[1000 Users](crowd icon) ->[API Gateway]->[Product Service]. - A "flood" of 1000 arrows labeled
SELECT *...flows from[Product Service]to[PostgreSQL DB]. - The Database (PostgreSQL DB) is drawn in red and "smoking" (overloaded).
- A diagram:
- Instructor Script:
- "Let's look back. In Module 4, we 'saved' the system from the 'lost money' disaster with SAGA. Our system is now very 'Safe'."
- "But now we have a new problem. [Point to diagram] The 'View Product Details' API (
GET /products/{id}) is our most-called API. If 1000 users view products at the same time, we are executing 1000SELECTqueries against the database." - "The database is the biggest 'bottleneck' for read operations. It runs on 'disk,' it's slow, and it will crash. We must 'protect' it."
Slide 5: Section Intro - P1: Understanding the Problem
- Content:
- PART 1
- UNDERSTANDING THE PROBLEM
- The Pain: DB Bottleneck & Caching Concepts
- Visualization:
- Professional layout with part number and title.
- Key visual: Split screen with [Icon: Database with flames (Overloaded)] on left and [Icon: Refrigerator (Cache concept)] on right.
- Instructor Script:
- "Let's begin with Part 1, where we diagnose the 'disease' before prescribing the 'medicine.'"
- "We will understand why the Database is the biggest bottleneck in read-heavy systems and how Caching solves this fundamental problem."
- "By the end of this section, you'll understand the core concept that powers every high-performance system: 'Copy frequently accessed data to a faster place.'"
Slide 6: P1 - "The Pain": The Database Bottleneck
- Content:
- WHY IS DATABASE ACCESS "EXPENSIVE"?
- 1. Slow:
- RAM (Memory) Access: ~10-100 nano-seconds.
- Disk (SSD) Access: ~100-500 micro-seconds.
- Round-trip (Network): ~1-10 milli-seconds.
- => A Database (Disk + Network) is millions of times slower than Memory.
- 2. Limited:
- A database has a limited number of concurrent 'Connections' (e.g., 100).
- Request #101 must wait in a queue.
- 3. Hard to Scale:
- Scaling 'Writes' on a DB is very hard.
- Visualization: *
[Image of memory vs disk speed comparison]
* A logarithmic scale comparison chart showing the *massive* speed difference: `RAM (Rocket)` vs `SSD (Car)` vs `HDD (Bicycle)`.- Instructor Script:
- "Why is the DB slow? Because it stores data on 'disk.' [Point to chart] Accessing 'RAM' (memory) is tens of thousands to millions of times faster than 'Disk' (SSD/HDD). It's the difference between a 'rocket' and a 'bicycle'."
- "Second, the DB is like a restaurant with only 100 'tables' (connections). The 101st person has to 'wait outside.' When 1000 requests hit, your system 'freezes'."
Slide 6: P1 (Continued) - The Solution: Caching Concepts & Benefits
- Content:
- THE SOLUTION: CACHING
- Concept: Storing a copy of frequently accessed data in a much faster storage layer (usually RAM).
- Analogy:
- Database (DB): The "Supermarket" (30 minutes away).
- Cache (RAM): Your home "Refrigerator."
- Instead of driving 30 minutes to the "Supermarket" (DB) every time you want milk (data), you keep a few cartons (a copy) in your "Refrigerator" (Cache) and get it instantly.
- Benefits:
- Low Latency: Faster response times (e.g., 200ms -> 5ms).
- Reduce Load: "Protect" the Database from unnecessary read requests.
- High Throughput: Serve many more requests per second.
- Visualization: *
- The "Refrigerator" analogy visualized:
[User] -> "I want milk"[Application] -> "Check Refrigerator (Cache)"(A small, fast [Icon: Refrigerator])[Cache (Refrigerator)] -> "Got milk!" (Fast Path: 1ms)- (If empty):
[Application] -> "Drive to Supermarket (DB)"(A large, slow [Icon: DB Building])(Slow Path: 200ms)
- The "Refrigerator" analogy visualized:
- Instructor Script:
- "The solution is Caching. Very simple: 'Copy' frequently used data to a faster place."
- "I love the 'Refrigerator' analogy. The Database is the 'Supermarket.' The Cache is your 'Refrigerator' at home."
- "You don't drive 30 minutes to the Supermarket (DB) just for one carton of milk (data). You buy 3 cartons and put them in the fridge (Cache). Next time, you open the fridge and get it in 1 second (1ms). Only when the fridge is empty (Cache Miss) do you have to drive to the supermarket."
- "The benefits are obvious: faster, reduced load on the DB, and can serve more users."
Slide 8: Section Intro - P2: Choosing the Right Tool
- Content:
- PART 2
- CHOOSING THE RIGHT TOOL
- Intro to Redis & Operations
- Visualization:
- Professional layout with part number and title.
- Key visual: Redis logo prominently displayed with [Icon: Toolbox] and [Icon: Settings/Gears] representing operations.
- Instructor Script:
- "Now that we understand the problem, let's meet the solution: Redis."
- "But we won't just 'install Redis.' We will configure it like professionals, understanding critical operational concepts like Eviction Policies and MaxMemory."
- "This section prepares you to run Redis in production, not just in development."
Slide 9: P2 - The Tool: Intro to Redis & Operations (UPGRADED)
-
Content:
- P2: THE TOOL - REDIS & OPERATIONS
- Redis (REmote DIctionary Server): The fastest, most popular In-Memory Key-Value "Refrigerator."
- Installation (Lab - Workshop 04):
# docker-compose.yml services: redis: image: redis:7-alpine ports: ['6379:6379'] # OPERATIONS UPGRADE command: redis-server --save 60 1 --loglevel warning --maxmemory 256mb --maxmemory-policy allkeys-lfu- UPGRADE: Operations (Operability)
maxmemory 256mb: The "Refrigerator" only has 256MB. What if it's full?maxmemory-policy allkeys-lfu: Eviction Policy.- When the fridge is full, throw away the "Least Frequently Used" (LFU) item.
- Others:
volatile-ttl(evict expiring items),allkeys-lru(evict Least Recently Used).
- Warning:
allkeys-lru(common) is vulnerable to scans.allkeys-lfuis often a better choice for read-heavy caches.
-
Visualization: *
- Left: Redis logo.
- Right:
docker-compose.ymlcode block withcommandargs highlighted. - A small diagram visualizing Eviction:
[Redis (Full)] -> [Policy (LFU)] -> [Evict LFU Key](An [Icon: Key] is shown being thrown away).
-
Instructor Script:
- "This is Redis. But we won't run it 'naively.' We'll run it like we do in 'production'."
- "[Point to code] We must set
maxmemory. Your 'refrigerator' is not infinite. 256MB." - "So, when it's 'full,' what do we throw out? That's the 'Eviction Policy.' We choose
allkeys-lfu: Throw out the item 'used least frequently.' This is often smarter thanLRU(least recently used) because it protects 'hot keys' from being evicted by a random scan."
Slide 8: P2 (Continued) - Operations & SLO (NEW)
- Content:
- "HARD PART" (OPERATIONS): METRICS & FALLBACK
- 1. What if the "Refrigerator" breaks? (Graceful Fallback)
- Problem: What if Redis crashes or times out (0.05s)?
- Bad Solution: Return a 500 error. -> Unacceptable.
- Good Solution (Graceful Degradation):
try... cache.get()except RedisTimeout:-> Log the Error, and continue to the DB.- The system slows down, but does not crash. (We will see this in the upgraded code).
- 2. Is the "Refrigerator" effective? (Metrics & SLO)
- We must measure the cache's effectiveness.
- Cache Hit Rate:
(Hits / (Hits + Misses))- SLO (Target): "The Hit Rate for
GET /productsmust be > 95%." - If Hit Rate < 95% -> Your cache is 'useless' (maybe TTL is too short, or keys are always stale).
- SLO (Target): "The Hit Rate for
- Cache Latency:
p99 cache.get() < 5ms.
- (Module 5 Preview): We will use OpenTelemetry (Tracing) to "wrap" our
cache.get/setcommands to measure these metrics.
- Visualization: * *
- Diagram 1 (Fallback):
[App] -> [Redis (Failed, X)] -> (Fallback Path, grayed out) -> [DB] - Diagram 2 (Metrics): A nice Grafana gauge dial showing 98% (Cache Hit Rate).
- Diagram 1 (Fallback):
- Instructor Script:
- "This operations part is critical. One, 'The fridge breaks' (Redis timeout/crash). [Point to Diagram 1] We are not allowed to return a 500 error to the user. Our code must
try...except; if the cache fails, we 'log it' and 'gracefully' go to the DB. The system 'slows down,' but 'does not die'." - "Two, how do we know the 'fridge' is working? [Point to Diagram 2] We must measure the 'Cache Hit Rate.' If 100 requests ask for milk, and 98 'hit' (98%), your cache is excellent. If it's 30%, your cache is 'useless'; you're wasting RAM."
- "We will learn how to measure this in Module 5 (Tracing)."
- "This operations part is critical. One, 'The fridge breaks' (Redis timeout/crash). [Point to Diagram 1] We are not allowed to return a 500 error to the user. Our code must
Slide 11: Section Intro - P3: Implementing the Strategy
- Content:
- PART 3
- IMPLEMENTING THE STRATEGY
- Cache-Aside Pattern & Production Code
- Visualization:
- Professional layout with part number and title.
- Key visual: Flowchart diagram with [Icon: Code brackets] and [Icon: Flowchart nodes] showing the Cache-Aside workflow.
- Instructor Script:
- "Now comes the core implementation. In Part 3, we will code the Cache-Aside pattern step-by-step."
- "This is not 'toy code.' This is production-ready code with Async operations, Graceful Fallback, Anti-Stampede mechanisms, and Jitter TTL."
- "By the end of this section, you will have written cache code that can survive in production systems handling thousands of requests per second."
Slide 12: P3 - Caching Strategy: Cache-Aside
- Content:
- STRATEGY #1: CACHE-ASIDE
- Philosophy: The "Dumb Refrigerator."
- The Application (You) is responsible: "Check Refrigerator (Cache). If empty, drive to Supermarket (DB), buy milk, put it in the Refrigerator, then drink it."
- This is the most common pattern and what we will Implement in the Lab.
- WORKFLOW (FLOWCHART):
- [Start] App receives
GET /product/{id}. - Create Cache Key (e.g.,
key = f"v1:product:{id}"). [Upgraded] - [Decision]
cache.get(key)? (Check Cache) - [YES - Cache Hit] (Found) ->
return data_from_cache. (Fast path) - [NO - Cache Miss] (Not found) -> Continue.
- [Process]
data = db.query("SELECT ..."). (Access DB) - [Decision]
dataexists? - [YES] -> [Process]
cache.set(key, data, ttl=300). (Save to Cache) - [End]
return data_from_db.
- [Start] App receives
- Visualization: *
- A detailed, clear flowchart showing these 9 steps. The Key (step 2) is updated (
v1:product:{id}). The "Cache Hit" branch (step 4) is colored green (Fast path), and the "Cache Miss" branch (steps 6-8) is colored orange (Slow path).
- A detailed, clear flowchart showing these 9 steps. The Key (step 2) is updated (
- Instructor Script:
- "Now for the main 'strategy': Cache-Aside. The 'Refrigerator is dumb,' and 'You' (the Application) must do all the work."
- "This is our 'golden' flowchart. [Point to flowchart]"
- "3. 'Ask' Redis. 4. If YES (Cache Hit), [point to green path] return, done! This is the 'highway' (fast path)."
- "5. If NO (Cache Miss), [point to orange path] we take the 'slow path.' 6. 'Drive to the supermarket' (access DB)."
- "8. [EMPHASIZE] Put it in the fridge (
redis.set) for next time. 9. Return the data."
Slide 10: P3 (Continued) - Cache-Aside (Code UPGRADED V2.0)
-
Content:
- CACHE-ASIDE IN PYTHON (PRODUCTION-READY) [Upgraded]
- (Code for Workshop 04 - Async FastAPI)
from redis.asyncio import Redis import asyncio, json, random # Connection Pool, 50ms timeout, 1 retry cache = Redis(host="localhost", port=6379, socket_timeout=0.05, retry_on_timeout=True, decode_responses=True) TTL_BASE = 300 TTL_JITTER = 60 @app.get("/products/{product_id}") async def get_product(product_id: int, db: Session = Depends(get_db)): key = f"v1:product:{product_id}" # UPGRADE: Versioned Key # 1. CHECK CACHE (with Graceful Fallback) try: cached = await cache.get(key) if cached: print("CACHE HIT!") return json.loads(cached) except Exception as e: print(f"REDIS ERROR (GET): {e}") # Log it! # Fallback: Treat as Cache Miss, get from DB. No crash. print("CACHE MISS!") # 2. UPGRADE: ANTI-STAMPEDE (Using Mutex SETNX) lock_key = f"lock:{key}" # Try to 'lock' for 5s. nx=True = "set only if not exists" got_lock = await cache.set(lock_key, "1", nx=True, ex=5) if got_lock: print("GOT LOCK! Rebuilding cache...") try: # 3. ACCESS DB (ONLY 1 PROCESS DOES THIS) data = db_query_product(product_id) # Your DB query func if not data: raise HTTPException(404, "Product not found") # UPGRADE: Jitter TTL (prevents mass expiration) ttl = TTL_BASE + random.randint(0, TTL_JITTER) await cache.set(key, json.dumps(data.dict()), ex=ttl) return data finally: await cache.delete(lock_key) # Release lock else: print("LOCKED! Waiting and retrying cache...") await asyncio.sleep(0.05) # Wait 50ms # Retry cache once, if still miss, fallback to DB cached = await cache.get(key) if cached: return json.loads(cached) # Final fallback: get from DB data = db_query_product(product_id) if not data: raise HTTPException(404, "Product not found") return data -
Visualization:
- Python/FastAPI (async) code block, with "UPGRADE" comments and different background colors highlighting the (1) Fallback, (2) Mutex, and (3) Jitter logic.
-
Instructor Script:
- "This is the 'production' code for Cache-Aside; it's 'immortal'."
- "[Point to 1] First, we
try...exceptthecache.get(). If Redis fails, we 'log it' and 'pretend' it was a cache miss. The system slows down, but does not crash." - "[Point to 2] This is 'Anti-Stampede.' When 10,000 users hit a 'Cache Miss,' we use
cache.set(nx=True)(SET if Not eXists) to 'acquire a lock.' Only one person 'gets the lock' (got_lock)." - "[Point to 3] Only the lock-holder gets to go to the 'supermarket' (DB). When they return, they 'stock the fridge' (
cache.set) with a 'randomized expiration' (Jitter TTL) so 1000 keys don't 'die' at the same time. Then they 'release the lock' (cache.delete)." - "What about the other 9,999 users? They 'fail' the lock (else), 'sleep' for 50ms, and 'retry the cache.' 99% of the time, this will now be a 'Cache Hit'."
Slide 14: Section Intro - P4 & P5: Mastering the Hard Parts
- Content:
- PART 4 & 5
- MASTERING THE HARD PARTS
- Cache Stampede & Cache Invalidation
- Visualization:
- Professional layout with part number and title.
- Key visual: Split screen with [Icon: Thunder/Lightning (Stampede)] on left and [Icon: Refresh/Sync arrows (Invalidation)] on right.
- Instructor Script:
- "We've implemented the basic Cache-Aside pattern. Now we tackle the two hardest problems in caching."
- "First, Cache Stampede - what happens when 10,000 users hit the same expired key simultaneously? Your database explodes."
- "Second, Cache Invalidation - one of the two hard problems in computer science. When data changes, how do we keep the cache in sync?"
- "These two problems separate junior developers from senior developers. Let's master them."
Slide 15: P4 - "Hard Part" #1: Cache Stampede (NEW)
- Content:
- "HARD PART" #1: CACHE STAMPEDE DISASTER
- Problem: 10,000 users all access the same "hot key" (e.g.,
product:123) at the exact moment it expires. - Result: 10,000 "Cache Misses" simultaneously -> 10,000 queries "hammer" the Database -> DB crashes.
- SOLUTIONS (Toolkit):
- 1. Mutex Lock (Using
SETNX):- What we just coded. Only 1 request gets the "lock" to rebuild the cache.
cache.set("lock:key", 1, nx=True, ex=5)
- 2. Jitter TTL:
- Add a random value to the TTL.
ttl = 300 + random(0, 60). - Prevents 1 million keys from expiring at the same second.
- Add a random value to the TTL.
- 3. Stale-While-Revalidate (SWR):
- When a key expires, still serve the old (stale) data, but asynchronously trigger a worker to "revalidate" (rebuild) the cache.
- Pro: User never waits (zero latency miss).
- Con: User might see 'stale' data for a short period.
- Visualization: *
- Diagram 1 (Disaster):
[10k Users] -> [Cache (MISS)] -> [10k Queries] -> [DB (DEAD)](Image of DB exploding). - Diagram 2 (Mutex Solution):
[10k Users] -> [Cache (MISS)] -> [Lock (SETNX)](A 'barrier' drops).-> [1 Query] -> [DB](Only 1 request passes).
- Diagram 1 (Disaster):
- Instructor Script:
- "I want to be clear about this 'disaster.' [Point to Diagram 1] Cache Stampede is when a 'hot key' expires, and all traffic 'flattens' your database."
- "We just coded Solution 1 (Mutex)—using
SETNXso only one person 'goes to the supermarket.' The other 9,999 wait for the 'milk' to be 'restocked'." - "Solution 2 (Jitter) is 'randomized expiration,' so all the milk cartons don't 'expire' at the same time."
- "Solution 3 (SWR) is very cool: The 'fridge' sees the milk is expired, gives you the old milk anyway, but 'silently' calls a worker to 'go buy new milk' and restock. The user never waits."
Slide 12: P5 - "Hard Part" #2: Cache Invalidation (UPGRADED)
- Content:
- "HARD PART" #2: CACHE INVALIDATION
- "What happens when an Admin updates the product price?"
- Strategy 1: TTL (Time-To-Live) - "Rely on Expiration"
- How:
cache.set(key, data, ex=300). - Pro: Extremely simple. Guarantees cache will refresh after 5 mins.
- Con: Accepts "staleness" for 5 minutes.
- Use: Non-sensitive data (like counts, comments).
- How:
- Strategy 2: Explicit Invalidation (Write-Through) - "Evict Immediately"
- Logic: When
PUT /product/123is called:db.update(price=150)cache.delete("product:123")(Delete key from cache)
- Con (Extremely Dangerous): "Dual Write Problem." If
db.update(OK) butcache.delete(FAILS)? The cache is 'stale' forever.
- Logic: When
- Strategy 3 (Best Practice): Event-based Invalidation (UPGRADED)
- (Combines Module 3 & 4: Outbox + RabbitMQ)
-
Product Service(APIPUT) ->db.update(...)+ SaveProductUpdatedevent toOUTBOX.
-
- (Relay) -> Publish
ProductUpdatedevent (withproduct_id) to RabbitMQ.
- (Relay) -> Publish
-
CacheInvalidator Service(A new Consumer) listens ->cache.delete("v1:product:{product_id}").
- Visualization: *
- Three clear mini-diagrams:
- TTL:
[Cache (Key, TTL)] -> [Auto-expire (Icon: Clock)] - Explicit:
[App] -> 1. [DB (Update)] -> 2. [Cache (Delete)](Arrow 2 is dashed, with an [Icon: Warning] for the Dual Write risk). - Event-based (Best): The full, "safe" diagram:
[App] -> [DB (Update) + Outbox (Save Event)](1 Transaction) ->[RabbitMQ]->[Cache Invalidator Service]->[Redis (DELETE key)].
- TTL:
- Three clear mini-diagrams:
- Instructor Script:
- "And this is the 'hardest part'. Strategy 1 (TTL), we accept 'stale milk' for 5 minutes."
- "Strategy 2 (Explicit Delete), is an 'anti-pattern' because of the 'Dual Write' risk. Never do this without also having a TTL."
- "Strategy 3: [EMPHASIZE] The 'best' way, combining everything we've learned. [Point to Diagram 3] The
Productservice only worries about 'updating the DB' and 'dropping a message in the Outbox' (Module 4). A separate 'bot' (Consumer, Module 3) 'listens' for that message and it is responsible for 'deleting the cache.' This is 'safe,' 'decoupled,' and 'resilient'."
Slide 13: P5 (Continued) - "Hard Part" #3: Key Design & Negative Cache (NEW)
- Content:
- "HARD PART" #3: KEY DESIGN & "EMPTY" CACHE
- 1. Key Design
- Rule:
[service]:[object]:[version]:[id] - Example:
product:v1:123,user:profile:v2:456 - Why
v1? (Versioning):- When you change the
schema(data structure) of the Product (e.g., add a new field), you can't 'delete' 10 million old keys. - How: Deploy new code. The new code reads & writes to key
product:v2:123. - All
v1cache keys will auto-expire without you 'deleting' them.
- When you change the
- Rule:
- 2. Negative Caching
- Problem: A hacker 'scans' non-existent IDs:
GET /product/9999999. - Result: 100% of these requests "Cache Miss" -> 100% "hammer" the DB (just to get a 404). The DB crashes from '404-scans.'
- Solution: Cache the "404 Not Found" result.
- How:
- When DB
return None(not found). cache.set("product:v1:9999999", "NULL", ex=60)(Cache a "NULL" value with a short TTL, e.g., 1 minute).- Next call:
cache.get()-> returns "NULL" ->return 404(No DB query needed).
- When DB
- Problem: A hacker 'scans' non-existent IDs:
- Visualization: * *
- Diagram 1 (Versioning):
[Code v1] -> [Cache (v1:product:123)]. A separate arrow:[Code v2] -> [Cache (v2:product:123)]. Thev1key has an [Icon: Clock] (auto-expires). - Diagram 2 (Negative):
[Hacker] -> GET /999->[Cache (MISS)]->[DB (404)]->[Cache SET key=999, val="NULL", ttl=60]. The Hacker's 2nd call is [Icon: Blocked] at the Cache.
- Diagram 1 (Versioning):
- Instructor Script:
- "Two final 'hard parts.' One, 'Key Design.' Never use
123as a key. Useproduct:v1:123. Why? Because when you upgrade your code and change the JSON structure, you just change the code to read/write tov2. All the oldv1cache keys will 'die' on their own (expire) without you 'deleting' 10 million keys." - "Two, 'Negative Caching.' [Point to Diagram 2] If a hacker tries to 'scan' for non-existent IDs, they will 'kill' your DB with a million 'SELECT... 404 Not Found' queries. The solution: Cache the '404' result. If the DB doesn't find it, you
cache.set(key_999, "NULL", ttl=60). For the next 60 seconds, all 'scans' for key 999 will 'hit' the 'NULL' cache and be blocked instantly."
- "Two final 'hard parts.' One, 'Key Design.' Never use
Slide 19: Section Intro - P6: Learning from the Giants
- Content:
- PART 6
- LEARNING FROM THE GIANTS
- Real-world Case Studies
- Visualization:
- Professional layout with part number and title.
- Key visual: Logos of major tech companies (Twitter, Facebook, Amazon) with [Icon: Globe/World] showing massive scale.
- Instructor Script:
- "Theory is important, but let's see how the giants do it. In Part 6, we examine real-world case studies from Twitter, Facebook, and E-commerce platforms."
- "These aren't toy examples. These are battle-tested patterns handling millions of users and billions of requests per day."
- "You'll see how they use Redis for timelines, counters, and other high-scale scenarios. These patterns are directly applicable to your projects."
Slide 20: P6 - Real-world Case Studies (NEW)
- Content:
- P6: REAL-WORLD CASE STUDIES
- Case Study 1: Twitter (Facebook/Tiktok) - "The Timeline"
- Problem: Millions of users scrolling timelines. Cannot query the DB for every 'scroll.'
- Solution: Fan-out on Write (Cache-based)
- Uses Redis
ListsorSorted Sets. - When "You" (User A) post: A worker pushes the Post ID into the "cache timeline" (Redis List) of all 10,000 of your followers.
- When a "Follower" (User B) opens the app: The app only reads from the Redis List
timeline:user_B(instantly, in-memory).
- Uses Redis
- This is "Write-Through" (Cache is the source of truth), not "Cache-Aside."
- Case Study 2: E-commerce - "The Counter"
- Problem: Counting "View Count" for a product.
- Bad Solution:
UPDATE products SET views = views + 1on every view -> "Locks" the table, crashes DB. - Good Solution (Redis
INCR):GET /product/123: App callsredis.incr("product:views:123").- The Redis
INCRcommand is "atomic" and in-memory (blazing fast). - A worker/cron job periodically (e.g., every 5 mins) reads these keys from Redis and syncs them back to the DB.
- Visualization: * *
- Diagram 1 (Timeline):
[User A (Post)] -> [Worker (Async)] -> [Redis List (Follower 1)], [Redis List (Follower 2)]...A separate flow:[Follower 1] -> (Read) -> [Redis List (Follower 1)](Very fast). - Diagram 2 (Counter):
[10k Users] -> [App (redis.incr)] -> [Redis](Fast, In-memory). A separate flow:[Worker (Cron)] -> [Redis (GET)] -> [DB (UPDATE)](Slow, periodic).
- Diagram 1 (Timeline):
- Instructor Script:
- "Now let's see two real-world case studies. [NEW] One, the 'Timeline' on Twitter/Facebook. When you scroll your newfeed, you are not querying the DB. You are reading a 'List' from Redis."
- "[Point to Diagram 1] When you 'Post,' a 'worker' (like in Module 3) takes your Post ID and 'shoves' it into the 'mailbox' (Redis List) of all your followers. This is 'Fan-out on Write.' It's 'expensive' to 'write,' but 'reading' (scrolling) is instantaneous."
- "Two, 'View Counts.' [Point to Diagram 2] Never
UPDATEyour DB on every view. Use the 'atomic'INCRcommand in Redis.redis.incr("product:views:123"). It's instant. Then, once every 5 minutes, a bot 'syncs' this total count back to the DB."
Slide 21: Section Intro - P7: Bringing It All Together
- Content:
- PART 7
- BRINGING IT ALL TOGETHER
- Best Practices, Workshop & Assignment
- Visualization:
- Professional layout with part number and title.
- Key visual: [Icon: Checklist with checkmarks] and [Icon: Rocket launching] representing completion and implementation.
- Instructor Script:
- "We've covered theory, implementation, hard problems, and real-world examples. Now it's time to bring everything together."
- "In Part 7, we'll consolidate everything into a Best Practices checklist, then prepare you for the hands-on workshop and assignment."
- "This is where theory becomes practice. By the end, you'll have production-ready caching code running in your own microservices."
Slide 22: P7 - Best Practices Summary (NEW)
- Content:
- P7: BEST PRACTICES SUMMARY (CHECKLIST)
- Design:
[ ]Use Cache-Aside for Read operations.[ ]Use Event-based Invalidation (with Outbox) for Write operations.[ ]Use Key Versioning (e.g.,v1:product:{id}).
- Performance:
[ ]Prevent Cache Stampede (useMutex/SETNX+Jitter TTL).[ ]Use Connection Pooling.
- Reliability:
[ ]Use Graceful Fallback (try...except) on Redis failure.[ ]Use Negative Caching (cache 404s) to block scans.
- Operations:
[ ]Configuremaxmemoryandmaxmemory-policy(e.g.,allkeys-lfu).[ ]MonitorCache Hit RateandLatency(SLO).
- Visualization:
- A 9-point checklist, clearly grouped into 4 categories (Design, Performance, Reliability, Operations). Each item has an [Icon: Checkbox].
- Instructor Script:
- "This is the 'final' slide that summarizes all the Best Practices an SME will expect when you work with cache. [NEW]"
- "For 'Design,' use Cache-Aside, Event-based Invalidation, and Versioned Keys."
- "For 'Performance,' prevent Stampede (Mutex, Jitter)."
- "For 'Reliability,' 'Fallback' on errors and use 'Negative Caching.'"
- "For 'Operations,' set 'maxmemory,' 'eviction policy,' and 'Monitor' your Hit Rate. These are the 9 golden rules."
Slide 23: P7 (Continued) - Workshop 04 Prep
- Content:
- IMPLEMENTATION LAB (WORKSHOP 04)
- Mission: Speed up
Product Service(Production-Ready). - Steps:
- Review (5 mins): Q&A on Assignment 04 (SAGA).
- Trainer-led (10 mins): Install Redis (Docker) (with
maxmemorycommand) + Installredis-py(async). - Step-by-step (Code-along) (70 mins):
- Apply Cache-Aside Pattern (Code V2.0 from Slide 10) to
GET /products/{id}. - Test: Test Hit/Miss. Test Fallback (by stopping Redis). Test Mutex (by calling 10x at once).
- Apply Cache-Aside Pattern (Code V2.0 from Slide 10) to
- Sharing (35 mins): Discuss Cache Invalidation - "How do we 'delete' this cache on
PUT?" (Discuss 3 strategies, focusing on Event-based).
- Visualization: *
- The Workshop's target architecture, with "Upgrades" noted:
[FastAPI (Cache-Aside + Mutex + Fallback)].
- The Workshop's target architecture, with "Upgrades" noted:
- Instructor Script:
- "This is our Workshop 04 plan."
- "After reviewing SAGA and running Redis (with production config), we will 'code-along' the V2.0 version from Slide 10."
- "We will code 4 versions. V1 is simple 'Get/Set'. V2 adds 'try...except' (Fallback). V3 adds 'Mutex' (Anti-Stampede). V4 adds 'Jitter'. These are the 4 'maturity' steps of cache code."
- "After, we will have a deep discussion on Invalidation."
Slide 24: P7 (Continued) - Assignment 05 Prep (UPGRADED V3.0)
- Content:
- PRACTICE TIME (ASSIGNMENT 05)
- Mission: Speed up
User Service. - Requirement:
- Apply the Cache-Aside Pattern to the
GET /users/profile/{user_id}API.
- Apply the Cache-Aside Pattern to the
- GRADING RUBRIC (UPGRADED V3.0):
- A. Logic & Reliability (40%)
[ ]Correct Cache-Aside flow (Get→Hit/Miss→Set) with a reasoned TTL.[ ]Anti-Stampede: HasMutex (SETNX)or SWR/Jitter.[ ]Fallback: Usestry...excepton Redis failure (does not 500).
- B. Key & Data Design (20%)
[ ]Key is versioned (e.g.,v1:user:profile:{id}).[ ](Bonus) Negative Cache: Caches "404 Not Found" results with a short TTL.
- C. Invalidation (25%)
[ ](Bonus) Implement "Explicit Delete" (cache.delete) onPUT /users/profile/{id}(and explain the Dual Write risk).[ ](Excellent) Describe (no code) how to use "Event-based Invalidation" (Outbox + RabbitMQ) to delete this cache.
- D. Operations & Observability (15%)
[ ]Clearly log all paths:CACHE_HIT,CACHE_MISS,CACHE_REBUILD,REDIS_ERROR_FALLBACK.
- Visualization: *
- A similar diagram, but for the
User Service. - A detailed checklist (Rubric A, B, C, D) based on your SME review.
- A similar diagram, but for the
- Instructor Script:
- "And this is your homework."
- "Similar to the workshop, you will apply the Cache-Aside pattern to the
User ServiceAPI." - "This is the new Rubric. [Point to Rubric] I am not just grading 'does it run.' I am grading (Section A) 'how you handle Stampede' and 'Redis failure.' I am grading (Section B) your 'key design.' The 'Excellent' grade (Section C) is for those who can connect this to Module 3/4 and 'describe' the safest Invalidation strategy."
Slide 25: Q&A
- Content:
- Q & A
- Questions & Answers
- Visualization:
- A clean, minimal slide. Just the large letters "Q&A".
- Instructor Script:
- "Thank you. We will take 10 minutes for Q&A on Caching."
Slide 26: Thank You & Next Module
- Content:
- THANK YOU!
- (Your Contact Info: Email, LinkedIn, etc.)
- COMING UP NEXT...
- Module 5: Observability (Tracing)
- Our system is 'Safe' (SAGA) and 'Fast' (Cache), but we are 'Flying Blind'.
- Visualization:
- A "teaser" for Module 5.
- An image: A dark airplane cockpit with no instruments. Next to it, a bright cockpit lit up with screens (Logs, Traces, Metrics).
- Instructor Script:
- "Thank you. We have successfully built a system that is 'Safe' (Module 4) and 'Fast' (Module 6)."
- "But we are 'Flying Blind.' When a user complains 'My order was slow,' we have no idea where it was slow. The API Gateway? The Order Service? The Payment Service? When an error happens, we have to 'grep' logs on 5 different services."
- "In Module 5, we are going to 'turn on the lights' in the cockpit. We will learn the 3 Pillars of 'Observability,' starting with Distributed Tracing."
Distributed Transactions & SAGA Pattern - Slides
Instructor slide content for Unit 4: managing distributed transactions across microservices using choreography and orchestration SAGA patterns
Observability: Logging, Tracing & Metrics - Slides
Instructor slide content for Unit 6: centralized logging with ELK, distributed tracing with Jaeger, and metrics with Prometheus