Async HTTP
ETag caching
HTTP requests
web development
caching techniques

Async http requests with ETag caching

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Asynchronous HTTP requests and ETag caching solve two common performance problems at once: blocking network calls and redundant payload downloads. Async execution keeps the application responsive, and ETag revalidation avoids transferring unchanged resources. Used together, they reduce latency, bandwidth, and backend load without complex infrastructure.

Core Sections

How ETag Revalidation Works

An ETag is a version token generated by the server for a specific representation of a resource. The client stores that token and sends it back in If-None-Match on later requests.

If the resource did not change, the server responds with 304 Not Modified and no body. If changed, the server returns 200 with fresh content and a new ETag. This pattern is ideal for configuration documents, profile data, and reference lists.

Async Client Request with Conditional Headers

A practical client keeps both payload and ETag in a local cache. On refresh, it revalidates instead of downloading blindly.

javascript
1const cache = new Map();
2
3async function fetchWithEtag(url) {
4  const entry = cache.get(url);
5  const headers = entry?.etag ? { "If-None-Match": entry.etag } : {};
6
7  const res = await fetch(url, { headers });
8
9  if (res.status === 304 && entry) {
10    return entry.data;
11  }
12
13  if (!res.ok) {
14    throw new Error(`HTTP ${res.status}`);
15  }
16
17  const data = await res.json();
18  const etag = res.headers.get("ETag");
19  cache.set(url, { etag, data });
20  return data;
21}
22
23fetchWithEtag("/api/settings").then(console.log).catch(console.error);

This keeps reads asynchronous and avoids stale network payloads when content is unchanged.

Server-Side ETag Generation in Node

Server implementation can use a content hash, version column, or updated timestamp to produce ETag values.

javascript
1import crypto from "node:crypto";
2import express from "express";
3
4const app = express();
5
6app.get("/api/settings", (req, res) => {
7  const payload = JSON.stringify({ featureA: true, maxItems: 25 });
8  const etag = crypto.createHash("sha1").update(payload).digest("hex");
9
10  if (req.header("if-none-match") === etag) {
11    return res.status(304).end();
12  }
13
14  res.set("ETag", etag);
15  res.json(JSON.parse(payload));
16});
17
18app.listen(3000);

Strong consistency is easier when ETag generation is deterministic for the exact response body.

Race Control for Repeated Async Requests

UI code often triggers repeated fetches from typing, tab switches, or polling. If requests overlap, stale responses can overwrite newer data. Track request tokens or use abort signals to keep order deterministic.

javascript
1let activeController;
2
3async function loadSettings() {
4  if (activeController) activeController.abort();
5  activeController = new AbortController();
6
7  const data = await fetchWithEtag("/api/settings", {
8    signal: activeController.signal,
9  });
10
11  renderSettings(data);
12}

Use one in-flight request per resource key in most UI cases. This avoids duplicate revalidation traffic and stale updates.

Cache Policy and Expiration Strategy

ETag revalidation is best for mutable data where freshness matters. Combine it with Cache-Control depending on requirements. Short max-age plus revalidation often balances speed and correctness.

http
Cache-Control: private, max-age=30
ETag: 7fd7c2c9a3

For APIs that change rarely, longer max-age reduces round trips. For volatile resources, keep max-age small and rely on lightweight 304 responses.

Observability and Testing

Measure the ratio of 304 to 200 responses to confirm the cache strategy works. High 200 rates on stable resources often signal missing or unstable ETag generation.

bash
curl -i http://localhost:3000/api/settings
curl -i -H 'If-None-Match: 7fd7c2c9a3' http://localhost:3000/api/settings

Automated tests should assert both unchanged and changed resource paths.

Common Pitfalls

  • Generating ETags from unstable values, which prevents 304 hits.
  • Returning 304 without previously caching the response body client-side.
  • Ignoring overlapping async requests and allowing stale UI overwrite.
  • Using ETag caching for sensitive user-specific data without private cache controls.
  • Forgetting to monitor 304 rates, making cache regressions hard to detect.

Summary

  • Async HTTP keeps clients responsive while requests are in flight.
  • ETags enable low-cost revalidation through If-None-Match and 304.
  • Deterministic ETag generation is essential for reliable cache behavior.
  • Request cancellation and in-flight control prevent stale response races.
  • Metrics and tests should validate that caching actually delivers benefit.

Course illustration
Course illustration

All Rights Reserved.