[{"data":1,"prerenderedAt":468},["ShallowReactive",2],{"category-data-jitter":3},[4],{"id":5,"title":6,"body":7,"description":456,"extension":457,"meta":458,"navigation":323,"ogImage":460,"path":464,"seo":465,"stem":466,"__hash__":467},"content/blogs/7. redis-ttl-jitter-and-how-i-almost-crashed-a-server.md","Redis TTL, Jitter, and How I Almost Crashed a Server 🚀",{"type":8,"value":9,"toc":447},"minimark",[10,15,22,25,29,36,54,61,65,68,74,77,137,140,143,147,158,161,166,169,177,183,187,193,204,351,365,369,372,381,384,398,405,409,412,423,429,432,443],[11,12,14],"h3",{"id":13},"recently-i-ran-into-an-interesting-redis-case-that-taught-me-a-big-lesson","Recently, I ran into an interesting Redis case that taught me a big lesson:",[16,17,18],"p",{},[19,20,21],"strong",{},"Infinite cache TTLs are like hoarding—things pile up until it’s a problem.",[23,24],"hr",{},[11,26,28],{"id":27},"the-setup-infinite-cache","The Setup: Infinite Cache",[16,30,31,32,35],{},"Once upon a time (okay, just a few months ago), we were saving some data in Redis with ",[19,33,34],{},"no expiration",". The idea was simple:",[37,38,39,48,51],"ul",{},[40,41,42,43,47],"li",{},"Data comes from another system (the ",[44,45,46],"em",{},"real"," source of truth).",[40,49,50],{},"We cache it in Redis for fast access.",[40,52,53],{},"Done. Easy. ✅",[16,55,56,57,60],{},"But here’s the problem: when you never expire cache, it ",[19,58,59],{},"keeps growing",". And growing. And growing. Like that drawer in your house where you throw every cable you’ve ever owned.",[11,62,64],{"id":63},"the-task-add-a-ttl","The Task: Add a TTL",[16,66,67],{},"One day, I got the task:",[69,70,71],"blockquote",{},[16,72,73],{},"“Please set a TTL of two weeks for this cache.”",[16,75,76],{},"Sounds easy, right? Just add:",[78,79,84],"pre",{"className":80,"code":81,"language":82,"meta":83,"style":83},"language-js shiki shiki-themes dracula","redis.set('mykey', value, 'EX', 1209600) // 2 weeks in seconds\n","js","",[85,86,87],"code",{"__ignoreMap":83},[88,89,92,96,100,103,107,111,113,116,118,121,123,126,130,133],"span",{"class":90,"line":91},"line",1,[88,93,95],{"class":94},"sCdxs","redis.",[88,97,99],{"class":98},"sAOxA","set",[88,101,102],{"class":94},"(",[88,104,106],{"class":105},"seVfx","'",[88,108,110],{"class":109},"s-mGx","mykey",[88,112,106],{"class":105},[88,114,115],{"class":94},", value, ",[88,117,106],{"class":105},[88,119,120],{"class":109},"EX",[88,122,106],{"class":105},[88,124,125],{"class":94},", ",[88,127,129],{"class":128},"sIQBb","1209600",[88,131,132],{"class":94},") ",[88,134,136],{"class":135},"shSDL","// 2 weeks in seconds\n",[16,138,139],{},"Boom. Done. Task finished. Go get coffee. ☕",[16,141,142],{},"Except… not really.",[11,144,146],{"id":145},"the-problem-cache-avalanche","The Problem: Cache Avalanche",[16,148,149,150,153,154,157],{},"Think about what happens ",[19,151,152],{},"two weeks later",".\nEvery single cached key expires ",[19,155,156],{},"at the same time",".",[16,159,160],{},"Suddenly, Redis says:",[69,162,163],{},[16,164,165],{},"“Sorry boss, no cache here!”",[16,167,168],{},"And then our poor backend server (the real source of truth) gets flooded with requests, like:",[78,170,175],{"className":171,"code":173,"language":174},[172],"language-text","HELP! SEND DATA! SEND DATA! SEND DATA!\n","text",[85,176,173],{"__ignoreMap":83},[16,178,179,180,157],{},"The server could literally crash under the unexpected load. This is called a ",[19,181,182],{},"cache avalanche",[11,184,186],{"id":185},"the-solution-add-jitter","The Solution: Add Jitter",[16,188,189,190],{},"The trick is simple but powerful: ",[19,191,192],{},"don’t let all keys expire at once.",[16,194,195,196,199,200,203],{},"Instead of setting ",[19,197,198],{},"exactly 2 weeks",", we add a little randomness (aka ",[44,201,202],{},"jitter","). For example:",[78,205,207],{"className":80,"code":206,"language":82,"meta":83,"style":83},"// Expire between 14 and 16 days\nconst baseTTL = 14 * 24 * 60 * 60 // 14 days\nconst jitter = Math.floor(Math.random() * (2 * 24 * 60 * 60)) // up to 2 days\nconst ttl = baseTTL + jitter\n\nredis.set('mykey', value, 'EX', ttl)\n",[85,208,209,214,248,300,318,325],{"__ignoreMap":83},[88,210,211],{"class":90,"line":91},[88,212,213],{"class":135},"// Expire between 14 and 16 days\n",[88,215,217,221,224,227,230,233,236,238,241,243,245],{"class":90,"line":216},2,[88,218,220],{"class":219},"s0Tla","const",[88,222,223],{"class":94}," baseTTL ",[88,225,226],{"class":219},"=",[88,228,229],{"class":128}," 14",[88,231,232],{"class":219}," *",[88,234,235],{"class":128}," 24",[88,237,232],{"class":219},[88,239,240],{"class":128}," 60",[88,242,232],{"class":219},[88,244,240],{"class":128},[88,246,247],{"class":135}," // 14 days\n",[88,249,251,253,256,258,261,264,267,270,273,276,279,282,284,286,288,290,292,294,297],{"class":90,"line":250},3,[88,252,220],{"class":219},[88,254,255],{"class":94}," jitter ",[88,257,226],{"class":219},[88,259,260],{"class":94}," Math.",[88,262,263],{"class":98},"floor",[88,265,266],{"class":94},"(Math.",[88,268,269],{"class":98},"random",[88,271,272],{"class":94},"() ",[88,274,275],{"class":219},"*",[88,277,278],{"class":94}," (",[88,280,281],{"class":128},"2",[88,283,232],{"class":219},[88,285,235],{"class":128},[88,287,232],{"class":219},[88,289,240],{"class":128},[88,291,232],{"class":219},[88,293,240],{"class":128},[88,295,296],{"class":94},")) ",[88,298,299],{"class":135},"// up to 2 days\n",[88,301,303,305,308,310,312,315],{"class":90,"line":302},4,[88,304,220],{"class":219},[88,306,307],{"class":94}," ttl ",[88,309,226],{"class":219},[88,311,223],{"class":94},[88,313,314],{"class":219},"+",[88,316,317],{"class":94}," jitter\n",[88,319,321],{"class":90,"line":320},5,[88,322,324],{"emptyLinePlaceholder":323},true,"\n",[88,326,328,330,332,334,336,338,340,342,344,346,348],{"class":90,"line":327},6,[88,329,95],{"class":94},[88,331,99],{"class":98},[88,333,102],{"class":94},[88,335,106],{"class":105},[88,337,110],{"class":109},[88,339,106],{"class":105},[88,341,115],{"class":94},[88,343,106],{"class":105},[88,345,120],{"class":109},[88,347,106],{"class":105},[88,349,350],{"class":94},", ttl)\n",[16,352,353,354,357,358,357,361,364],{},"Now some keys expire in ",[19,355,356],{},"14 days",", some in ",[19,359,360],{},"15",[19,362,363],{},"16",".\nWhich means requests trickle back to the server instead of hitting it like a tsunami. 🌊",[11,366,368],{"id":367},"why-it-matters","Why It Matters",[16,370,371],{},"Without jitter:",[37,373,374],{},[40,375,376,377,380],{},"Day 14 → server gets ",[19,378,379],{},"millions of requests at once",". Boom. 🔥",[16,382,383],{},"With jitter:",[37,385,386,389,392,395],{},[40,387,388],{},"Day 14 → some requests",[40,390,391],{},"Day 15 → some more",[40,393,394],{},"Day 16 → a few more",[40,396,397],{},"Server is chill. 😎",[16,399,400,401,404],{},"This small change can ",[19,402,403],{},"save your entire system"," from crashing.",[11,406,408],{"id":407},"final-thoughts","Final Thoughts",[16,410,411],{},"Caching is powerful, but it comes with hidden gotchas.",[37,413,414,417,420],{},[40,415,416],{},"Infinite TTL? Your cache becomes a junkyard.",[40,418,419],{},"Fixed TTL? Your server might collapse in 14 days like a time bomb.",[40,421,422],{},"TTL with jitter? Balanced, safe, and production-ready.",[16,424,425,426],{},"So the next time you set a cache TTL, remember:\n👉 ",[44,427,428],{},"Always sprinkle some randomness in your Redis life.",[16,430,431],{},"Your future self (and your backend servers) will thank you. 🙏",[16,433,434,435,438,439,442],{},"Do you want me to also add a ",[19,436,437],{},"diagram (ASCII or image idea)"," showing the difference between ",[44,440,441],{},"no jitter vs jitter"," so it’s more visually clear for the blog?",[444,445,446],"style",{},"html pre.shiki code .sCdxs, html code.shiki .sCdxs{--shiki-default:#F8F8F2}html pre.shiki code .sAOxA, html code.shiki .sAOxA{--shiki-default:#50FA7B}html pre.shiki code .seVfx, html code.shiki .seVfx{--shiki-default:#E9F284}html pre.shiki code .s-mGx, html code.shiki .s-mGx{--shiki-default:#F1FA8C}html pre.shiki code .sIQBb, html code.shiki .sIQBb{--shiki-default:#BD93F9}html pre.shiki code .shSDL, html code.shiki .shSDL{--shiki-default:#6272A4}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s0Tla, html code.shiki .s0Tla{--shiki-default:#FF79C6}",{"title":83,"searchDepth":216,"depth":216,"links":448},[449,450,451,452,453,454,455],{"id":13,"depth":250,"text":14},{"id":27,"depth":250,"text":28},{"id":63,"depth":250,"text":64},{"id":145,"depth":250,"text":146},{"id":185,"depth":250,"text":186},{"id":367,"depth":250,"text":368},{"id":407,"depth":250,"text":408},"Recently, I ran into an interesting Redis case that taught me a big lesson Infinite cache TTLs are like hoarding—things pile up until it’s a problem.","md",{"date":459,"image":460,"alt":6,"tags":461,"published":323},"18th Sep 2025","/blogs-img/blog7.png",[462,463,202],"redis","ttl","/blogs/redis-ttl-jitter-and-how-i-almost-crashed-a-server",{"title":6,"description":456},"blogs/7. redis-ttl-jitter-and-how-i-almost-crashed-a-server","JbcEvgf3w-iEDJUcwtcUwf69SX0KVJFwDCBrjw7iIl4",1770700754802]