Skip to content
-
Subscribe to our newsletter & never miss our best posts. Subscribe Now!
Developer Hint

Your Ultimate Guide to Web Development.

Developer Hint

Your Ultimate Guide to Web Development.

  • Home
  • Web Development
  • Tech Explained
  • Developer Tools
  • Contact Us
  • Home
  • Web Development
  • Tech Explained
  • Developer Tools
  • Contact Us
Close

Search

Subscribe
Developer Hint

Your Ultimate Guide to Web Development.

Developer Hint

Your Ultimate Guide to Web Development.

  • Home
  • Web Development
  • Tech Explained
  • Developer Tools
  • Contact Us
  • Home
  • Web Development
  • Tech Explained
  • Developer Tools
  • Contact Us
Close

Search

Subscribe
Home/Tech Explained/What Is a Cache and How Does It Work? A Developer’s Guide
What Is A Cache And How Does It Work
Tech Explained

What Is a Cache and How Does It Work? A Developer’s Guide

By Developer Hint
October 15, 2026 8 Min Read
0

Open a site you’ve never been to and watch it load. Then open it again. The second time, it almost always feels quicker, sometimes dramatically so, and nothing about your internet connection changed. What changed is that your browser kept some of what it downloaded the first time and reused it.

That’s a cache. It’s a stored copy of something that was slow or expensive to get, kept somewhere closer or faster, so the next request can skip the expensive part. The idea is old and shows up at every level of computing, from the memory inside your processor to the servers that deliver video to millions of people. Once you recognize the pattern, you start seeing it everywhere, and you start understanding why certain bugs happen only after you deploy.

The Vocabulary You Need

A handful of terms come up in every caching conversation, and they’re simpler than they sound. When a request finds what it needs in the cache, that’s a hit. When it doesn’t, and the system has to go get the data from the original source, that’s a miss. The proportion of requests that hit is the hit ratio, and it’s the number people usually care about when they tune a cache.

Cached data doesn’t live forever. Most caches attach a TTL, short for time to live, which is how long a copy counts as fresh. After that, it’s stale and has to be checked or replaced. When a cache runs out of room, it evicts something to make space, and a common rule is to drop whatever was used least recently, known as LRU. And when the original data changes and the cached copy is now wrong, you need to invalidate it. That last one is where most of the pain lives, and we’ll come back to it.

Caches Exist at Every Layer

A single web request can pass through several caches before it reaches the code you wrote.

LayerWhere It LivesWhat It Saves
CPU cacheInside the processorTrips to main memory
DNS cacheYour OS, browser, and resolverRepeated domain lookups
Browser cacheThe visitor’s deviceRe-downloading files and responses
CDN cacheServers spread around the worldDistance to your origin server
Application cacheMemory on your servers, or Redis and MemcachedRepeating expensive computations and queries
Database cacheInside the database engineRe-reading data from disk

Each one trades a bit of freshness for speed. As a web developer, you mostly control the middle three: the browser, the CDN, and your own application. That’s where the rest of this post lives.

How the Browser Cache Decides What to Keep

Your server doesn’t push files into the browser cache. It sends a response with headers, and the headers tell the browser how long it may reuse the file. The main one is Cache-Control:

HTTP/1.1 200 OK
Content-Type: text/css
Cache-Control: public, max-age=86400

That says any cache may store this file, and it stays fresh for 86,400 seconds, one day. For the next day, the browser won’t even contact the server for it. It just uses its stored copy, which is why cached pages can load instantly and even work offline in some cases.

The Directives That Matter

max-age sets the freshness lifetime in seconds. public allows shared caches like CDNs to store the response, while private restricts it to the visitor’s own browser, which is what you want for anything personalized. And then there are two directives that sound alike and do very different things, which trips up a lot of people.

no-store means exactly what it says: don’t keep a copy anywhere. Use it for sensitive responses. no-cache does not mean “don’t cache.” It means the browser may store the file but must check with the server before using it each time. If you want a response never to be stored, no-cache is the wrong choice.

What Happens When a Cached File Goes Stale

A stale copy isn’t automatically thrown away. The browser can ask the server whether its copy is still good, using a validator. The server includes one in the original response, usually an ETag, which is a fingerprint of the file’s contents:

HTTP/1.1 200 OK
ETag: "33a64df5"
Cache-Control: max-age=60

Once the minute is up, the browser sends the fingerprint back with its next request:

GET /styles.css HTTP/1.1
If-None-Match: "33a64df5"

If the file hasn’t changed, the server answers with a tiny 304 Not Modified and no body, and the browser reuses what it has. If it has changed, the server sends the new file with a fresh 200. You save the download but not the round trip, which is a good compromise for files that change unpredictably.

The Deploy Problem and How Fingerprinted Filenames Solve It

Here’s a situation almost every developer meets. You deploy a fix, refresh, and everything looks right. Then a user reports the old broken version. The cause is usually a long max-age on a file whose name never changed: the browser has a copy it considers fresh, so it never asks for the new one.

The standard fix is to put a fingerprint in the filename itself. Instead of app.js, you ship app.3f9a1c7b.js, where the hash comes from the file’s contents. When the code changes, the name changes, and the browser treats it as a completely different file that it has never seen. Build tools like Vite and webpack do this for you automatically.

That unlocks an aggressive strategy for those files, because a hashed file can never be stale. Its name changes whenever its content does:

Cache-Control: public, max-age=31536000, immutable

That’s one year, and immutable tells the browser not to bother revalidating even on a reload. The one file that can’t use this trick is your HTML page, because its name has to stay index.html or whatever the URL maps to. So HTML gets a short lifetime or no-cache, and it points at the new hashed files as soon as they exist. That combination, short-lived HTML pointing at permanently cached assets, is behind most fast, correctly updating sites.

Best for: use this as a starting point for headers by file type.

ResourceSuggested Cache-Control
Hashed JS and CSS bundlespublic, max-age=31536000, immutable
HTML pagesno-cache (store, but revalidate each time)
Images without hashes in the filenameA moderate max-age like one day, plus an ETag
User-specific API responsesprivate, with a short max-age or no-store if sensitive

In Express, you can set a lifetime on static files directly:

app.use(express.static("public", {
    maxAge: "1y",
    immutable: true
}));

Only do that for a folder of fingerprinted files. Applying a one-year lifetime to a folder of files that keep their names is how you create the stale-deploy problem on purpose.

CDN Caching

A CDN is a cache with geography. It keeps copies of your content on servers in many regions, so a visitor in Mogadishu gets files from a nearby machine rather than waiting on your origin server on another continent. That cuts latency for the visitor and traffic for you, and it’s one of the cheapest ways to improve load speed, which matters for the LCP metric we cover in our Core Web Vitals guide.

CDNs read the same Cache-Control headers, with one addition. s-maxage sets a lifetime for shared caches only, so you can let the CDN hold a page for ten minutes while browsers revalidate every time. You can also purge a CDN’s copy through its dashboard or API when you need an update to appear everywhere right away.

There’s one mistake here worth stating clearly, because the consequences are bad. If a response is personalized, like an account page or anything that depends on a login cookie, and it goes out marked public, a shared cache can store it and serve it to the next visitor. People have ended up looking at each other’s data this way. Anything tied to a user should be private or no-store. The cookie guide explains how login sessions work and why those responses are personal.

Caching Inside Your Own Application

Browser and CDN caches handle files and responses. For work your server does itself, like a slow database query or a call to someone else’s API, you cache the result in your application. The usual pattern is called cache-aside: check the cache first, and only on a miss do the real work and save the answer for next time.

const cache = new Map();

async function getProduct(id) {
    const cached = cache.get(id);

    if (cached && cached.expires > Date.now()) {
        return cached.value; // hit
    }

    const product = await db.findProduct(id); // miss: do the slow work
    cache.set(id, { value: product, expires: Date.now() + 60_000 }); // 60 second TTL

    return product;
}

That in-memory Map works for a single server, but it disappears on restart and isn’t shared between multiple servers. Once you run more than one instance, teams typically move this to Redis or Memcached, which hold the cache in a separate fast service that every instance can read. The pattern stays the same. Only the storage changes.

The sixty-second TTL is a deliberate choice. A product page that’s up to a minute out of date is usually fine, and it can turn a thousand database queries into one. A stock count on a checkout page is a different story. Deciding how stale is acceptable for each piece of data is the actual design work in caching.

The Hard Part: Keeping Caches Honest

There’s an old joke that the two hard problems in computer science are naming things and cache invalidation. It lands because every cache is a promise that a copy is close enough to the truth, and the original keeps changing underneath it.

You have a few options for keeping that promise. The simplest is to let the TTL expire and accept some staleness, which is fine more often than people expect. When that’s not good enough, you can delete or update the cached entry whenever the underlying data is written, so the next read rebuilds it fresh. Another approach is versioning the key itself, like product:42:v7, so a change simply starts using a new key and the old one ages out.

There’s also a middle path built into HTTP called stale-while-revalidate. With Cache-Control: max-age=60, stale-while-revalidate=300, the browser can show a slightly stale copy instantly while it fetches a fresh one in the background. The visitor gets speed, and the next visit gets current data. For content like article listings or dashboards, that tradeoff is often exactly right.

Seeing Your Caches at Work

Open DevTools and go to the Network tab. Reload a page you’ve visited and look at the Size column. Entries that say “(disk cache)” or “(memory cache)” never touched the network at all. A request showing status 304 went to the server, got told nothing changed, and reused its copy. Click any request and check the response headers for Cache-Control, ETag, and Age, which reports how many seconds a shared cache has held the response. CDNs usually add their own header too, such as cf-cache-status on Cloudflare, which says plainly whether you got a hit or a miss.

One DevTools habit will save you hours: tick “Disable cache” in the Network tab while you work. It only applies while DevTools is open, but it stops your own browser from fooling you. When you want to test what a real returning visitor sees, untick it, or use a hard reload (Ctrl+Shift+R, or Cmd+Shift+R on a Mac) to bypass the cache for one load.

A Question to Ask Before Blaming the Code

When something works on your machine but not for users, or a change you deployed doesn’t show up, suspect a cache before you suspect your logic. Then narrow it down by layer. Does a hard reload fix it? Then it’s the browser. Does it differ by region, or look fine on a direct request to your origin server? Then it’s the CDN. Does the API return old data while the database has new data? Then it’s your application cache. Each layer has its own headers and its own way to clear it.

The useful question for every cached thing you build is a short one: how stale is acceptable here, and who is allowed to store it. Answer that, and most of the headers and TTLs choose themselves.


Discover more from Developer Hint

Subscribe to get the latest posts sent to your email.

Content Disclosure
This content was created with the assistance of AI tools and thoroughly reviewed, fact-checked, and refined by a human editor to ensure accuracy, clarity, and usefulness for readers.
Advertisements
banner

Tags:

cacheCDNHTTPRediswebsite performance
Author

Developer Hint

Follow Me
Other Articles
What Is A Cookie On A Website
Previous

What Is a Cookie on a Website? How Browser Cookies Actually Work

What Is A Cms A Beginners Guide
Next

What Is a CMS? A Beginner’s Guide

No Comment! Be the first one.

Leave a ReplyCancel reply

Random Posts

  • How to Stop Tutorial Hell and Start Building Real ProjectsHow to Stop Tutorial Hell and Start Building Real Projects
  • REST API vs GraphQL: What’s the Difference? A Beginner’s GuideREST API vs GraphQL: What’s the Difference? A Beginner’s Guide
  • What Is Minification in Web Development? CSS, JS, and HTML ExplainedWhat Is Minification in Web Development? CSS, JS, and HTML Explained
  • What Is an IP Address? Meaning, Types, and How It Works (Complete Beginnerโ€™s Guide)What Is an IP Address? Meaning, Types, and How It Works (Complete Beginnerโ€™s Guide)
  • Elementor vs Gutenberg: Which WordPress Page Builder Should You Use?Elementor vs Gutenberg: Which WordPress Page Builder Should You Use?

Popular

Random Posts

  • What Is an IP Address? Meaning, Types, and How It Works (Complete Beginnerโ€™s Guide)What Is an IP Address? Meaning, Types, and How It Works (Complete Beginnerโ€™s Guide)
  • What Is a Web Server? A Beginner’s Guide to How Websites WorkWhat Is a Web Server? A Beginner’s Guide to How Websites Work
  • npm vs npx: What’s the Difference? A Beginner’s Guidenpm vs npx: What’s the Difference? A Beginner’s Guide
  • CSS Selectors Explained: A Practical Guide for Every Skill LevelCSS Selectors Explained: A Practical Guide for Every Skill Level
  • HTML vs HTML5: What’s the Real Difference?HTML vs HTML5: What’s the Real Difference?

Legal pages

  • About Us
  • Privacy Policy
  • Terms and Conditions
  • Disclaimer

Trending

Copyright 2026 โ€” Developer Hint. All rights reserved.

Necessary cookies enable essential site features like secure log-ins and consent preference adjustments. They do not store personal data.
None
Functional cookies support features like content sharing on social media, collecting feedback, and enabling third-party tools.
None
Analytical cookies track visitor interactions, providing insights on metrics like visitor count, bounce rate, and traffic sources.
None
Advertisement cookies deliver personalized ads based on your previous visits and analyze the effectiveness of ad campaigns.
None
Unclassified cookies are cookies that we are in the process of classifying, together with the providers of individual cookies.
None