DEV Community

Cover image for HTTP Caching 101: Everything You Need to Know
Leapcell
Leapcell

Posted on

HTTP Caching 101: Everything You Need to Know

Cover

What is HTTP Caching

HTTP caching is a technology that improves web performance by reducing server load, speeding up client response times, and saving network bandwidth. There are two types of HTTP caching: forced caching and negotiated caching.

Forced Caching

Forced caching allows the client to use locally cached resources directly within a specified time period without sending a request to the server. Forced caching is controlled by response headers specified by the server, primarily through two fields: Cache-Control and Expires.

Cache-Control

Cache-Control is a general-purpose header that specifies the maximum validity period (max-age), whether the cache can be shared (public or private), and whether modifications are allowed (no-cache or no-store).

Example:

Cache-Control: max-age=3600
Enter fullscreen mode Exit fullscreen mode

The above indicates that the resource is valid for 3600 seconds and can be cached.

Expires

Expires is a deprecated field that specifies the absolute expiration time for the cache.

Example:

Expires: Wed, 23 Aug 2024 03:36:26 GMT
Enter fullscreen mode Exit fullscreen mode

This means the resource will expire at 3:36:26 AM on August 23, 2024.

If both Cache-Control and Expires are present, Cache-Control takes precedence.

Negotiated Caching

Negotiated caching requires the client to check with the server if the resource has been updated for every request. If not updated, the server responds with a 304 status code and an empty response body, allowing the client to continue using the local cache. If updated, the server returns a 200 status code and the new resource, replacing the local cache. Negotiated caching involves headers from both the server and client, primarily Last-Modified/If-Modified-Since and ETag/If-None-Match.

Last-Modified/If-Modified-Since

Last-Modified is a server-side field indicating the last modification time of the resource. Example:

Last-Modified: Tue, 22 Aug 2024 02:36:26 GMT
Enter fullscreen mode Exit fullscreen mode

This means the resource was last modified on August 22, 2024, at 2:36:26 AM.

If-Modified-Since is a client-side field indicating the last retrieval time of the resource. Example:

If-Modified-Since: Tue, 22 Aug 2024 02:36:26 GMT
Enter fullscreen mode Exit fullscreen mode

This means the client retrieved the resource on August 22, 2024, at 2:36:26 AM.

If the two timestamps are equal or Last-Modified is earlier, the resource has not been updated. If Last-Modified is later, the resource has been updated.

ETag/If-None-Match

ETag is a server-side field representing the unique identifier of a resource. Example:

ETag: '5d3a9f6d-1f86'
Enter fullscreen mode Exit fullscreen mode

This indicates the resource's identifier is "5d3a9f6d-1f86".

If-None-Match is a client-side field indicating the expected identifier of a resource. Example:

If-None-Match: '5d3a9f6d-1f86'
Enter fullscreen mode Exit fullscreen mode

This indicates the client expects the resource identifier to be "5d3a9f6d-1f86".

If the two values match, the resource has not been updated. If they differ, the resource has been updated.

HTTP Caching Best Practices

Combining negotiated caching and forced caching can effectively reduce unnecessary network requests while ensuring users always have the latest content.

General Approach:

Forced Caching: For static resources (e.g., CSS, JS, images), set a long cache duration. This allows browsers to directly retrieve resources from local storage without contacting the server.

Negotiated Caching: For resources that may change, use negotiated caching. Browsers will send requests to check if the resource has changed. If not, the server responds with a 304 Not Modified response, allowing the browser to use the local cache. If the resource has changed, the server responds with a 200 OK and the updated resource.

Example Implementation:

Suppose we are using Express.js as the backend framework:

const express = require('express');
const app = express();

// Forced caching: Set cache for static resources
app.use(
  '/static',
  express.static('public', {
    maxAge: '1y', // Cache duration is one year
  })
);

// Negotiated caching: Using ETag and Last-Modified
app.get('/resource', (req, res) => {
  const content = '...'; // Fetch the resource content
  const etag = generateETag(content); // Generate ETag

  // Check the If-None-Match header
  if (req.headers['if-none-match'] === etag) {
    res.status(304).end(); // Resource unchanged, return 304
  } else {
    res.setHeader('ETag', etag);
    res.send(content); // Resource changed, return new content
  }
});

function generateETag(content) {
  return require('crypto').createHash('md5').update(content).digest('hex');
}

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

Key Considerations

  • Version Control: To maximize forced caching effectiveness, include version information in resource URLs, e.g., /static/js/main.2024082301.js. When resources are updated, change the version number to ensure users always get the latest version.

  • Cost of Negotiated Caching: While negotiated caching reduces unnecessary data transfer, it still requires a network round trip. For resources that rarely change, forced caching might be more efficient.


We are Leapcell, your top choice for hosting backend projects

Leapcell

Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:

Multi-Language Support

  • Develop with Node.js, Python, Go, or Rust.

Deploy unlimited projects for free

  • pay only for usage — no requests, no charges.

Unbeatable Cost Efficiency

  • Pay-as-you-go with no idle charges.
  • Example: $25 supports 6.94M requests at a 60ms average response time.

Streamlined Developer Experience

  • Intuitive UI for effortless setup.
  • Fully automated CI/CD pipelines and GitOps integration.
  • Real-time metrics and logging for actionable insights.

Effortless Scalability and High Performance

  • Auto-scaling to handle high concurrency with ease.
  • Zero operational overhead — just focus on building.

Explore more in the Documentation!

Try Leapcell

Follow us on X: @LeapcellHQ


Read on our blog

Top comments (0)