AJAX - Conditional AJAX Requests with ETags and Last-Modified Headers

Introduction

Conditional AJAX requests are a technique used to reduce unnecessary data transfer between a web browser and a server. In a normal AJAX request, the browser asks the server for a resource, and the server sends the resource back even when the content has not changed since the browser last requested it.

For example, suppose a webpage loads a list of products using AJAX. The browser requests the product data every time the user refreshes the list. If the product information has not changed, downloading the complete response again wastes bandwidth and increases the amount of work performed by both the client and server.

Conditional requests solve this problem by allowing the browser to ask the server whether the resource has changed. If it has not changed, the server can respond with 304 Not Modified instead of sending the complete resource again.

Two important HTTP mechanisms used for this purpose are ETag and Last-Modified.

What Is an ETag?

ETag stands for Entity Tag. It is a value generated by the server to identify a particular version of a resource.

For example, when a browser requests:

GET /products

the server may return:

HTTP/1.1 200 OK
ETag: "products-v42"
Content-Type: application/json

The response body could contain:

{
  "products": [
    {
      "id": 1,
      "name": "Laptop"
    },
    {
      "id": 2,
      "name": "Keyboard"
    }
  ]
}

The ETag represents the current version of the resource. If the resource changes, the server normally generates a different ETag.

For example:

ETag: "products-v43"

This tells the browser that the resource has a newer version.

How ETag Works with AJAX

When the browser receives an ETag, it can store it along with the cached response.

Later, when JavaScript makes another AJAX request, the browser can send the stored ETag using the If-None-Match request header:

GET /products
If-None-Match: "products-v42"

The server compares this value with the current ETag.

If the resource has not changed, the server responds:

HTTP/1.1 304 Not Modified

The server does not need to send the complete JSON response again.

If the resource has changed, the server sends the new content:

HTTP/1.1 200 OK
ETag: "products-v43"
Content-Type: application/json

followed by the updated data.

What Is Last-Modified?

Last-Modified is another HTTP mechanism for identifying when a resource was last changed.

For example, the server might return:

HTTP/1.1 200 OK
Last-Modified: Sun, 20 Sep 2026 10:30:00 GMT

This tells the browser when the resource was last modified.

When the browser requests the same resource again, it can send:

If-Modified-Since: Sun, 20 Sep 2026 10:30:00 GMT

The server checks whether the resource has changed after that time.

If it has not changed, the server returns:

HTTP/1.1 304 Not Modified

If the resource has changed, the server returns the updated content with a 200 OK response.

ETag vs Last-Modified

Both mechanisms are designed to determine whether a cached resource is still valid, but they work differently.

Feature ETag Last-Modified
Identifies Specific version of a resource Modification time
Request header If-None-Match If-Modified-Since
Response header ETag Last-Modified
Accuracy Generally more precise Based on modification time
Useful for Detecting exact resource changes Time-based validation
Server response when unchanged 304 Not Modified 304 Not Modified

ETags can be particularly useful when a resource may change multiple times within a short period, because a version identifier can distinguish different representations more precisely than a timestamp.

Example of an AJAX Request

Consider a JavaScript application that retrieves user information:

fetch("/api/users")
  .then(response => {
    if (response.status === 304) {
      console.log("User data has not changed.");
      return null;
    }

    return response.json();
  })
  .then(data => {
    if (data) {
      console.log(data);
    }
  });

In a real application, browsers and HTTP caching mechanisms generally handle conditional requests automatically when the appropriate caching headers are present. Therefore, application code does not always need to manually manage ETags.

The server might return:

HTTP/1.1 200 OK
Cache-Control: max-age=60
ETag: "users-20260920"
Content-Type: application/json

On a later request, the browser can use the cached information and validate it with the server.

Complete Request Flow

The basic process can be understood in several steps.

Step 1: Initial AJAX Request

The browser requests the resource:

GET /api/users

Step 2: Server Sends Resource

The server responds:

HTTP/1.1 200 OK
ETag: "users-100"

along with the requested data.

Step 3: Browser Stores the Response

The browser stores the response according to the caching rules supplied by the server.

Step 4: Another AJAX Request Occurs

The application requests the same resource again.

The browser can send:

If-None-Match: "users-100"

Step 5: Server Checks the Version

The server compares "users-100" with the current ETag.

If both are identical, the server knows that the resource has not changed.

Step 6: Server Returns 304

The server responds:

HTTP/1.1 304 Not Modified

The previously cached response can then be reused.

If the ETag is different, the server instead returns the updated resource with 200 OK.

Why 304 Not Modified Is Important

The 304 Not Modified response is useful because the server does not have to transfer the complete resource again.

Suppose an AJAX application downloads a 500 KB JSON response. If the information has not changed, repeatedly downloading 500 KB would consume unnecessary network bandwidth.

With conditional requests, the browser can validate the resource and receive a much smaller response indicating that the existing cached version remains valid.

This can help reduce:

  • Network bandwidth usage

  • Server response data

  • Repeated data transfers

  • Loading overhead

  • Unnecessary processing

Example with Last-Modified

Suppose an AJAX application requests news articles.

The server responds:

HTTP/1.1 200 OK
Last-Modified: Sun, 20 Sep 2026 08:00:00 GMT
Content-Type: application/json

Later, the browser sends:

GET /api/news
If-Modified-Since: Sun, 20 Sep 2026 08:00:00 GMT

If no article has been modified since that time, the server responds:

HTTP/1.1 304 Not Modified

The browser can continue using the cached news data.

If an article was updated at 09:15, the server sends:

HTTP/1.1 200 OK
Last-Modified: Sun, 20 Sep 2026 09:15:00 GMT

along with the new response.

Advantages

Conditional AJAX requests provide several benefits.

Reduced bandwidth: Unchanged resources do not need to be transferred repeatedly.

Improved performance: Smaller responses can reduce network activity and improve application responsiveness.

Lower server load: The server does not need to generate and transfer complete responses when the resource has not changed.

Better caching: ETags and modification timestamps allow cached resources to be validated efficiently.

Suitable for frequently requested data: Applications that repeatedly request relatively stable information can benefit significantly.

Limitations

Conditional requests also have some limitations.

First, the server must correctly implement HTTP caching and validation headers.

Second, an ETag or modification timestamp does not eliminate the need for the browser to communicate with the server when validation is required.

Third, Last-Modified relies on timestamps and may not always represent changes with the same precision as an ETag.

Finally, caching behavior can be affected by HTTP cache-control directives, proxies, browsers, and server configuration.

ETag and Last-Modified Together

A server can provide both mechanisms:

HTTP/1.1 200 OK
ETag: "article-205"
Last-Modified: Sun, 20 Sep 2026 10:00:00 GMT

This provides the client and intermediate caching systems with two ways of validating the resource.

The ETag identifies the representation, while Last-Modified provides information about when it was last changed.

Practical AJAX Use Cases

Conditional requests are useful in applications where the same information is requested repeatedly but does not change frequently.

Examples include:

  • News article listings

  • Product catalogs

  • User profiles

  • Public announcements

  • Configuration data

  • Documentation pages

  • Dashboard information

  • Frequently accessed API resources

For example, a dashboard may request server statistics every minute. If the underlying information has not changed, conditional requests can prevent the entire response from being downloaded unnecessarily.

Conclusion

Conditional AJAX requests with ETags and Last-Modified headers provide an efficient way to validate previously retrieved resources. Instead of always downloading the complete response, the browser can ask the server whether its cached version is still current.

An ETag identifies a particular version of a resource, while Last-Modified identifies when the resource was last changed. When the resource remains unchanged, the server can return 304 Not Modified, allowing the browser to reuse its cached copy.

This approach is especially valuable for AJAX applications that repeatedly request data, because it can reduce unnecessary network transfers while maintaining up-to-date information.