Quiz

Explain the concept of caching and how it can be used to improve performance

Topics
JavaScriptPerformance

TL;DR

Caching reuses a previously computed or fetched result to reduce latency, bandwidth, and server work. A cache is correct only when its key, freshness policy, and invalidation behavior match the data. For versioned static assets, long-lived HTTP caching is effective; personalized or frequently changing API data usually needs revalidation or a shorter lifetime. Service workers add offline and custom routing capabilities, but also add another cache that must be updated deliberately.


Cache lookup and revalidation

A cache improves repeat access only when its freshness and invalidation rules let it answer safely.

Cache lookup decision flow

Caching trades freshness and invalidation complexity for lower latency, network use, or computation, so the policy matters as much as the storage layer.

The concept of caching and how it can be used to improve performance

What is caching?

Caching is a technique used to store copies of files or data in a temporary storage location, known as a cache, to reduce the time it takes to access them. The primary goal of caching is to improve performance by minimizing the need to fetch data from the original source repeatedly.

Types of caching

Browser cache

The browser cache stores copies of web pages, images, and other resources locally on the user's device. When a user revisits a website, the browser can load these resources from the cache instead of fetching them from the server, resulting in faster load times.

Service workers

Service workers are scripts that run in the background and can intercept network requests. They can cache resources and serve them from the cache, even when the user is offline. This can improve performance and provide a better user experience.

HTTP caching

HTTP caching involves using HTTP headers to control how and when resources are cached. Common headers include Cache-Control, Expires, and ETag.

How caching improves performance

Reduced latency

By storing frequently accessed data closer to the user, caching reduces the time it takes to retrieve that data. This results in faster load times and a smoother user experience.

Reduced server load

Caching reduces the number of requests made to the server, which can help decrease server load and improve overall performance.

Offline access

With service workers, cached resources can be served even when the user is offline, keeping the application usable without a network connection.

Implementing caching

HTTP caching example

For a content-hashed asset such as /assets/app.a1b2c3.js, the server can send:

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

When the content changes, the build emits a new URL. By contrast, an authenticated account response should not receive this policy. It might use Cache-Control: private, no-cache so the browser may store it but must revalidate before reuse, or no-store when storage is inappropriate.

Service worker example

const CACHE_NAME = 'app-shell-v2';
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(['/index.html', '/styles.css', '/app.js']);
}),
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(
caches
.match(event.request)
.then((cachedResponse) => cachedResponse || fetch(event.request)),
);
});

This cache-first strategy suits versioned static assets, but can serve stale API data. A production service worker also needs version cleanup, update handling, error behavior, and a strategy chosen per request type. Libraries such as Workbox can implement these patterns, but do not remove the need to define freshness rules.

Cache failure modes

  • Stale data: A long lifetime or cache-first strategy returns an outdated result.
  • Incorrect keys: A cache omits a locale, authorization scope, or query parameter and returns one user's variant to another context.
  • Unbounded growth: An in-memory cache has no size or time-based eviction.
  • Cache stampede: Many misses recompute the same expensive result simultaneously.
  • Sensitive data retention: Private responses are stored in a shared or persistent cache.

Measure hit rate and user-visible latency. A cache with few hits or expensive invalidation can add complexity without improving performance.

Further reading

Exercises

Check your understanding
Beta
Check your understanding Exercise 1 of 2
Check your understanding Exercise 1 of 2

Which caching strategy is the best fit for a versioned asset named app.8f3a1.js, whose URL changes whenever its contents change?