[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"navigation":3,"\u002Fblog\u002Fdns-caching-in-nodejs-supercharge-your-apps-speed-and-reliability":58,"\u002Fblog\u002Fdns-caching-in-nodejs-supercharge-your-apps-speed-and-reliability-surround":832},[4],{"title":5,"path":6,"stem":7,"children":8,"page":57},"Blog","\u002Fblog","blog",[9,13,17,21,25,29,33,37,41,45,49,53],{"title":10,"path":11,"stem":12},"A Guide to Server-Side Rendering (SSR) with Vite and React.js","\u002Fblog\u002Fa-guide-to-server-side-rendering-ssr-with-vite-and-reactjs","blog\u002Fa-guide-to-server-side-rendering-ssr-with-vite-and-reactjs",{"title":14,"path":15,"stem":16},"🔄 Background DNS Refresh in Node.js: Keeping Cached IPs Updated","\u002Fblog\u002Fbackground-dns-refresh-in-nodejs-keeping-cached-ips-updated","blog\u002Fbackground-dns-refresh-in-nodejs-keeping-cached-ips-updated",{"title":18,"path":19,"stem":20},"Comprehensive Guide: Encrypting Images, Uploading to Cloudinary, and Serving Them Securely","\u002Fblog\u002Fcomprehensive-guide-encrypting-images-uploading-to-cloudinary-and-serving-them-securely","blog\u002Fcomprehensive-guide-encrypting-images-uploading-to-cloudinary-and-serving-them-securely",{"title":22,"path":23,"stem":24},"Comprehensive Guide to Using Uploadthing with Express and Typescript","\u002Fblog\u002Fcomprehensive-guide-to-using-uploadthing-with-express-and-typescript","blog\u002Fcomprehensive-guide-to-using-uploadthing-with-express-and-typescript",{"title":26,"path":27,"stem":28},"🌐 DNS Caching in Node.js: Supercharge Your App's Speed & Reliability 🚀","\u002Fblog\u002Fdns-caching-in-nodejs-supercharge-your-apps-speed-and-reliability","blog\u002Fdns-caching-in-nodejs-supercharge-your-apps-speed-and-reliability",{"title":30,"path":31,"stem":32},"Enhancing Redis for Message Queues: Using External Databases for Payload Storage","\u002Fblog\u002Fenhancing-redis-for-message-queues-using-external-databases-for-payload-storage","blog\u002Fenhancing-redis-for-message-queues-using-external-databases-for-payload-storage",{"title":34,"path":35,"stem":36},"Full Stack Learning Management System (LMS) with MERN Stack: A Complete Guide","\u002Fblog\u002Ffull-stack-learning-management-system-lms-with-mern-stack-a-complete-guide","blog\u002Ffull-stack-learning-management-system-lms-with-mern-stack-a-complete-guide",{"title":38,"path":39,"stem":40},"Getting Started with Redis: Elevating Your Web Applications","\u002Fblog\u002Fgetting-started-with-redis-elevating-your-web-applications","blog\u002Fgetting-started-with-redis-elevating-your-web-applications",{"title":42,"path":43,"stem":44},"How Queues Enhance Your Application Development Process","\u002Fblog\u002Fhow-queues-enhance-your-application-development-process","blog\u002Fhow-queues-enhance-your-application-development-process",{"title":46,"path":47,"stem":48},"Next-Gen E-Learning: Transforming Education for Students and Creators","\u002Fblog\u002Fnext-gen-e-learning-transforming-education-for-students-and-creators","blog\u002Fnext-gen-e-learning-transforming-education-for-students-and-creators",{"title":50,"path":51,"stem":52},"Single Sign-On (SSO) Implementation Using Passport.js in TypeScript","\u002Fblog\u002Fsingle-sign-on-sso-implementation-using-passportjs-in-typescript","blog\u002Fsingle-sign-on-sso-implementation-using-passportjs-in-typescript",{"title":54,"path":55,"stem":56},"Using Multer for Local File Uploads: Benefits, Trade-offs, and Cloud Transfer Integration","\u002Fblog\u002Fusing-multer-for-local-file-uploads-benefits-trade-offs-and-cloud-transfer-integration","blog\u002Fusing-multer-for-local-file-uploads-benefits-trade-offs-and-cloud-transfer-integration",false,{"id":59,"title":26,"author":60,"body":66,"date":823,"description":824,"extension":825,"image":826,"meta":827,"minRead":828,"navigation":829,"path":27,"seo":830,"stem":28,"__hash__":831},"blog\u002Fblog\u002Fdns-caching-in-nodejs-supercharge-your-apps-speed-and-reliability.md",{"name":61,"to":62,"username":63,"avatar":64},"Sachin Thapa","https:\u002F\u002Fsachinthapa.hashnode.dev\u002F","sachinthapa572",{"src":65,"alt":61},"https:\u002F\u002Fcdn.hashnode.com\u002Fres\u002Fhashnode\u002Fimage\u002Fupload\u002Fv1733546636355\u002Fa4ae8ce5-eb4c-4ed8-ab9d-15a4b8f32ea5.png",{"type":67,"value":68,"toc":775},"minimark",[69,77,80,89,94,105,113,118,139,146,148,155,247,258,268,273,275,282,287,302,307,319,321,328,333,340,346,351,362,369,375,377,394,401,405,424,428,452,454,461,465,479,483,503,509,511,518,583,588,590,596,601,624,629,631,637,642,662,668,670,676,683,703,710,727,729,736,739,745,756,762,770],[70,71,72,76],"p",{},[73,74,75],"em",{},"Ever wondered why your app feels sluggish when fetching data from APIs? The hidden culprit might be DNS lookups! Let's fix that."," 💡",[78,79],"hr",{},[81,82,84,85],"h2",{"id":83},"why-should-you-care-about-dns","🎯 ",[86,87,88],"strong",{},"Why Should You Care About DNS?",[70,90,91],{},[73,92,93],{},"(Spoiler: Your app's speed depends on it!)",[70,95,96,97,100,101,104],{},"Imagine you're sending letters 📮. Every time you mail one, you first run to the post office to ask, ",[73,98,99],{},"\"Hey, what's Alice's address again?\""," Sounds exhausting, right? That's exactly what your app does with ",[86,102,103],{},"DNS lookups","!",[106,107,109,110],"h3",{"id":108},"dns-resolution-101","🔍 ",[86,111,112],{},"DNS Resolution 101",[70,114,115],{},[73,116,117],{},"(In 10 seconds!)",[119,120,121,130,136],"ol",{},[122,123,124,125,129],"li",{},"You request ",[126,127,128],"code",{},"api.catfacts.com"," 🐱",[122,131,132,133],{},"DNS servers translate it to an IP like ",[126,134,135],{},"104.18.22.34",[122,137,138],{},"Your app connects to that IP",[70,140,141,142,145],{},"But what if this happens ",[86,143,144],{},"every single request","? 😱",[78,147],{},[81,149,151,152],{"id":150},"the-5-deadly-sins-of-frequent-dns-lookups","🚨 ",[86,153,154],{},"The 5 Deadly Sins of Frequent DNS Lookups",[156,157,158,174],"table",{},[159,160,161],"thead",{},[162,163,164,168,171],"tr",{},[165,166,167],"th",{},"Sin",[165,169,170],{},"Symptom",[165,172,173],{},"Real-World Impact",[175,176,177,191,208,221,234],"tbody",{},[162,178,179,185,188],{},[180,181,182],"td",{},[86,183,184],{},"Latency Overload",[180,186,187],{},"\"Why is this API call taking 300ms?!\"",[180,189,190],{},"Users rage-quit your slow app 🐢💔",[162,192,193,198,205],{},[180,194,195],{},[86,196,197],{},"DNS Server Spam",[180,199,200,201,204],{},"Your app becomes ",[73,202,203],{},"that neighbor"," who won't stop ringing doorbells",[180,206,207],{},"DNS providers block you 🚫",[162,209,210,215,218],{},[180,211,212],{},[86,213,214],{},"Single Point of Failure",[180,216,217],{},"DNS goes down → Your app crashes",[180,219,220],{},"Midnight outage calls 😱📉",[162,222,223,228,231],{},[180,224,225],{},[86,226,227],{},"Wasted Resources",[180,229,230],{},"CPU cycles burned on repetitive lookups",[180,232,233],{},"Cloud bill shock 💸🔥",[162,235,236,241,244],{},[180,237,238],{},[86,239,240],{},"API Rate Limiting",[180,242,243],{},"\"Error 429: Too Many Requests\"",[180,245,246],{},"Sales fail during Black Friday 🛒❌",[106,248,250,251,254,255],{"id":249},"bad-code-alert-dont-do-this","👎 ",[86,252,253],{},"Bad Code Alert"," ",[73,256,257],{},"(Don't Do This!)",[259,260,265],"pre",{"className":261,"code":263,"language":264},[262],"language-text","\u002F\u002F ❌ Naive implementation - DNS lookup EVERY time!\nasync function fetchCatFact() {\n  const { address } = await dns.resolve4('api.catfacts.com');\n  return fetch(`http:\u002F\u002F${address}\u002Ffact`, {\n    headers: { Host: 'api.catfacts.com' } \u002F\u002F 🚩 Redundant work!\n  });\n}\n","text",[126,266,263],{"__ignoreMap":267},"",[70,269,270],{},[73,271,272],{},"This is like re-checking Alice's address for every letter!",[78,274],{},[81,276,278,279],{"id":277},"dns-caching-to-the-rescue","🦸 ",[86,280,281],{},"DNS Caching to the Rescue!",[70,283,284],{},[86,285,286],{},"How it works:",[119,288,289,292,299],{},[122,290,291],{},"First request → Ask DNS for IP 📡",[122,293,294,295,298],{},"Store IP with a ",[73,296,297],{},"\"Best Before\""," timestamp (TTL) ⏳",[122,300,301],{},"Subsequent requests → Use cached IP until expiry ♻️",[70,303,304],{},[86,305,306],{},"Benefits:",[308,309,310,313,316],"ul",{},[122,311,312],{},"⚡ 90%+ faster API calls",[122,314,315],{},"🛡️ Survives DNS outages",[122,317,318],{},"📉 80% fewer DNS queries",[78,320],{},[81,322,324,325],{"id":323},"lets-build-a-dns-cache-in-nodejs","👨💻 ",[86,326,327],{},"Let's Build a DNS Cache in Node.js!",[70,329,330],{},[73,331,332],{},"(Code Walkthrough for Humans)",[106,334,336,337],{"id":335},"step-1-create-a-smart-cache","🧠 ",[86,338,339],{},"Step 1: Create a Smart Cache",[259,341,344],{"className":342,"code":343,"language":264},[262],"\u002F\u002F Our cache: { domain: { address: '1.2.3.4', expiresAt: 169876543210 } }\nconst dnsCache = new Map(); \n\nasync function getCachedIP(domain) {\n  const now = Date.now();\n\n  \u002F\u002F 🕵️ Check cache first\n  if (dnsCache.has(domain)) {\n    const { address, expiresAt } = dnsCache.get(domain);\n    if (now \u003C expiresAt) {\n      console.log(`✨ Using cached IP for ${domain}: ${address}`);\n      return address; \u002F\u002F Cache hit!\n    }\n  }\n\n  \u002F\u002F 🆕 DNS lookup when cache misses\u002Fexpires\n  try {\n    const records = await dns.promises.resolve4(domain, { ttl: true });\n    if (records.length === 0) throw new Error('No records found');\n\n    const { address, ttl } = records[0];\n    const expiresAt = now + ttl * 1000; \u002F\u002F TTL is in seconds\n\n    dnsCache.set(domain, { address, expiresAt });\n    console.log(`🚀 Fetched fresh IP for ${domain}: ${address} (TTL: ${ttl}s)`);\n    return address;\n  } catch (error) {\n    console.error(`🔥 DNS failed for ${domain}:`, error.message);\n    return null; \u002F\u002F Graceful degradation\n  }\n}\n",[126,345,343],{"__ignoreMap":267},[70,347,348],{},[86,349,350],{},"Key Features:",[308,352,353,356,359],{},[122,354,355],{},"Automatic TTL handling ⏰",[122,357,358],{},"Error logging for debugging 🐞",[122,360,361],{},"Graceful failure handling 🤗",[106,363,365,366],{"id":364},"step-2-supercharged-api-endpoint","🚀 ",[86,367,368],{},"Step 2: Supercharged API Endpoint",[259,370,373],{"className":371,"code":372,"language":264},[262],"app.get('\u002Fcat-fact', async (req, res) => {\n  try {\n    const ip = await getCachedIP('api.catfacts.com');\n    if (!ip) throw new Error('DNS unavailable');\n\n    \u002F\u002F 🎯 Magic: Use IP but keep 'Host' header!\n    const response = await fetch(`http:\u002F\u002F${ip}\u002Ffact`, {\n      headers: { Host: 'api.catfacts.com' } \u002F\u002F Required for SSL\u002FSNI\n    });\n\n    const fact = await response.json();\n    res.json({ fact });\n  } catch (error) {\n    res.status(500).json({ error: \"Failed to fetch cat facts 😿\" });\n  }\n});\n",[126,374,372],{"__ignoreMap":267},[78,376],{},[70,378,379,382,385,386,389,390,393],{},[86,380,381],{},"Wait, why the Host header?",[383,384],"br",{},"\nModern servers host multiple sites on one IP. The ",[126,387,388],{},"Host"," header tells them ",[73,391,392],{},"\"I want catfacts.com, not dogmemes.com!\""," 🐶≠🐱",[81,395,397,398],{"id":396},"ttl-time-to-live-deep-dive","⏳ ",[86,399,400],{},"TTL (Time-To-Live) Deep Dive",[106,402,404],{"id":403},"what-developers-often-miss","What Developers Often Miss:",[308,406,407,414],{},[122,408,409,410,413],{},"TTL is set by the ",[86,411,412],{},"DNS provider",", not your app (e.g., Cloudflare defaults to 300s).",[122,415,416,419,420,423],{},[86,417,418],{},"Stale Cache Risks",": Using expired IPs can lead to ",[126,421,422],{},"ENOTFOUND"," errors.",[106,425,427],{"id":426},"best-practices","Best Practices:",[119,429,430,436,446],{},[122,431,432,435],{},[86,433,434],{},"Respect TTL",": Never override it—providers rotate IPs for load balancing.",[122,437,438,441,442,445],{},[86,439,440],{},"Buffer Refresh",": Refresh cache at ",[126,443,444],{},"TTL - 10%"," to avoid stale entries.",[122,447,448,451],{},[86,449,450],{},"Fallback Mechani sm",": If cached IP fails, retry with fresh DNS.",[78,453],{},[81,455,457,458],{"id":456},"️-security-considerations-for-dns-caching","🛡️ ",[86,459,460],{},"Security Considerations for DNS Caching",[106,462,464],{"id":463},"risks","Risks:",[119,466,467,473],{},[122,468,469,472],{},[86,470,471],{},"Cache Poisoning",": Malicious actors inject fake DNS records.",[122,474,475,478],{},[86,476,477],{},"Stale IPs",": Expired entries pointing to decommissioned servers.",[106,480,482],{"id":481},"mitigations","Mitigations:",[308,484,485,491,497],{},[122,486,487,490],{},[86,488,489],{},"DNSSEC Validation",": Ensure DNS responses are digitally signed.",[122,492,493,496],{},[86,494,495],{},"TTL Sanity Checks",": Reject TTLs > 1 hour (common in attacks).",[122,498,499,502],{},[86,500,501],{},"Isolate Caches",": Use separate caches per environment (prod vs. dev).",[259,504,507],{"className":505,"code":506,"language":264},[262],"\u002F\u002F Example: DNSSEC Validation (using external library)\nimport { validateDNSSEC } from 'dnssec-validator';\n\nasync function secureResolve(domain) {\n  const records = await dns.resolve4(domain, { ttl: true });\n  const isValid = await validateDNSSEC(domain, records);\n  if (!isValid) throw new Error('DNSSEC validation failed');\n  return records;\n}\n",[126,508,506],{"__ignoreMap":267},[78,510],{},[81,512,514,515],{"id":513},"performance-showdown-cache-vs-no-cache","📊 ",[86,516,517],{},"Performance Showdown: Cache vs No Cache",[156,519,520,539],{},[159,521,522],{},[162,523,524,527,530,533,536],{},[165,525,526],{},"Scenario",[165,528,529],{},"100 Requests",[165,531,532],{},"Latency",[165,534,535],{},"DNS Queries",[165,537,538],{},"Risk of Failure",[175,540,541,558],{},[162,542,543,546,549,552,555],{},[180,544,545],{},"No Cache",[180,547,548],{},"1.2 sec\u002Freq",[180,550,551],{},"12,000ms",[180,553,554],{},"100",[180,556,557],{},"High 😰",[162,559,560,565,570,575,580],{},[180,561,562],{},[86,563,564],{},"With Cache",[180,566,567],{},[86,568,569],{},"0.3 sec\u002Freq",[180,571,572],{},[86,573,574],{},"300ms",[180,576,577],{},[86,578,579],{},"1",[180,581,582],{},"Low 😎",[70,584,585],{},[73,586,587],{},"Results from testing a weather API endpoint (AWS t3.micro)",[78,589],{},[81,591,151,593],{"id":592},"when-not-to-cache-dns",[86,594,595],{},"When NOT to Cache DNS",[70,597,598],{},[73,599,600],{},"(Yes, there are exceptions!)",[308,602,603,610,617],{},[122,604,605,606,609],{},"🕵️‍♂️ ",[86,607,608],{},"Dynamic IPs",": Some APIs rotate IPs frequently",[122,611,612,613,616],{},"🌍 ",[86,614,615],{},"Geo-DNS",": IPs change based on user location",[122,618,619,620,623],{},"🔄 ",[86,621,622],{},"Load Balancers",": IPs might point to different servers",[70,625,626],{},[73,627,628],{},"Always check your API provider's DNS behavior!",[78,630],{},[81,632,365,634],{"id":633},"take-it-to-production",[86,635,636],{},"Take It to Production!",[70,638,639],{},[86,640,641],{},"Pro Tips:",[119,643,644,650,656],{},[122,645,646,649],{},[86,647,648],{},"Background Refresh",": Update cached IPs 5 mins before TTL expires",[122,651,652,655],{},[86,653,654],{},"Fallback Mechanism",": If cached IP fails, retry with fresh DNS",[122,657,658,661],{},[86,659,660],{},"Monitoring",": Track cache hit ratio and DNS failures (Prometheus\u002FGrafana)",[259,663,666],{"className":664,"code":665,"language":264},[262],"\u002F\u002F Bonus: Auto-refresh cache 5 minutes before TTL expires\nfunction scheduleRefresh(domain, ttlSeconds) {\n  const refreshTime = (ttlSeconds - 300) * 1000; \u002F\u002F 5 mins buffer\n  setTimeout(async () => {\n    await getCachedIP(domain); \u002F\u002F Force refresh\n  }, refreshTime);\n}\n",[126,667,665],{"__ignoreMap":267},[78,669],{},[81,671,612,673],{"id":672},"real-world-impact-case-studies",[86,674,675],{},"Real-World Impact: Case Studies",[106,677,679,680],{"id":678},"_1-e-commerce-giant","1. ",[86,681,682],{},"E-Commerce Giant",[308,684,685,691,697],{},[122,686,687,690],{},[86,688,689],{},"Problem",": 500ms added latency during Black Friday sales.",[122,692,693,696],{},[86,694,695],{},"Solution",": DNS caching + TTL-aware prefetching.",[122,698,699,702],{},[86,700,701],{},"Result",": 40% reduction in API latency; $2M+ saved in potential lost sales.",[106,704,706,707],{"id":705},"_2-iot-platform","2. ",[86,708,709],{},"IoT Platform",[308,711,712,717,722],{},[122,713,714,716],{},[86,715,689],{},": 10,000 devices polling every 30s caused DNS rate limits.",[122,718,719,721],{},[86,720,695],{},": Edge-side caching with Cloudflare Workers.",[122,723,724,726],{},[86,725,701],{},": DNS queries reduced by 99.9%.",[78,728],{},[81,730,732,733],{"id":731},"your-turn","📣 ",[86,734,735],{},"Your Turn!",[70,737,738],{},"Ready to turbocharge your Node.js apps? Implement DNS caching today and watch your performance metrics soar! 🚀",[70,740,741,744],{},[86,742,743],{},"Challenge",": Try adding a cache size limit (LRU cache) to prevent memory bloat!",[70,746,747,748,751,752,755],{},"👉 ",[86,749,750],{},"Up Next",": ",[73,753,754],{},"\"Zero-Downtime DNS: Background Refresh & Circuit Breakers\""," – Ensure 100% uptime even during DNS storms! ⚡",[70,757,758,761],{},[86,759,760],{},"Let me know in the comments",":",[308,763,764,767],{},[122,765,766],{},"Have you hit DNS-related outages before?",[122,768,769],{},"What other performance tricks do you use?",[70,771,772],{},[73,773,774],{},"Keep shipping awesome stuff! 🚢",{"title":267,"searchDepth":776,"depth":776,"links":777},2,[778,784,789,791,798,803,808,810,812,814,821],{"id":83,"depth":776,"text":779,"children":780},"🎯 Why Should You Care About DNS?",[781],{"id":108,"depth":782,"text":783},3,"🔍 DNS Resolution 101",{"id":150,"depth":776,"text":785,"children":786},"🚨 The 5 Deadly Sins of Frequent DNS Lookups",[787],{"id":249,"depth":782,"text":788},"👎 Bad Code Alert (Don't Do This!)",{"id":277,"depth":776,"text":790},"🦸 DNS Caching to the Rescue!",{"id":323,"depth":776,"text":792,"children":793},"👨💻 Let's Build a DNS Cache in Node.js!",[794,796],{"id":335,"depth":782,"text":795},"🧠 Step 1: Create a Smart Cache",{"id":364,"depth":782,"text":797},"🚀 Step 2: Supercharged API Endpoint",{"id":396,"depth":776,"text":799,"children":800},"⏳ TTL (Time-To-Live) Deep Dive",[801,802],{"id":403,"depth":782,"text":404},{"id":426,"depth":782,"text":427},{"id":456,"depth":776,"text":804,"children":805},"🛡️ Security Considerations for DNS Caching",[806,807],{"id":463,"depth":782,"text":464},{"id":481,"depth":782,"text":482},{"id":513,"depth":776,"text":809},"📊 Performance Showdown: Cache vs No Cache",{"id":592,"depth":776,"text":811},"🚨 When NOT to Cache DNS",{"id":633,"depth":776,"text":813},"🚀 Take It to Production!",{"id":672,"depth":776,"text":815,"children":816},"🌍 Real-World Impact: Case Studies",[817,819],{"id":678,"depth":782,"text":818},"1. E-Commerce Giant",{"id":705,"depth":782,"text":820},"2. IoT Platform",{"id":731,"depth":776,"text":822},"📣 Your Turn!","2025-03-11","Optimize API performance in Node.js with DNS caching. Learn how caching reduces latency, prevents disruptions, and enhances reliability","md","https:\u002F\u002Fcdn.hashnode.com\u002Fres\u002Fhashnode\u002Fimage\u002Fupload\u002Fv1741709904653\u002Fefc07a6b-2354-45d3-8810-f1b66ff11053.png",{},4,true,{"title":26,"description":824},"MHszLAY3CjJFQGiZWkNnc5u1xbDOisS-E53R2m3XXlU",[833,835],{"title":22,"path":23,"stem":24,"description":834,"children":-1},"This note provides a detailed exploration of setting up file uploads using Uploadthing in an Express.js application with TypeScript, focusing on security best practices and the potential use of signed URLs.",{"title":30,"path":31,"stem":32,"description":836,"children":-1},"Use external databases for payloads in Redis queues to reduce memory use, lower costs, and improve scalability for small to medium projects"]