Client and Network Caching

The HTTP protocol has built-in support for caching requests — this is specified in RFC 7234. While a lot of focus is put on trimming server responses to reduce the payload — it is still faster to re-use a response. This is what cache headers can help with.

Idempotent and Safe

The HTTP methods can be categorized according to if they are safe and idempotent. This categorization is important when you consider what can be cached.

Safe methods are HTTP methods that do not modify resources and therefore can be safely cached. GET , HEAD and OPTIONS are all safe methods.

An idempotent HTTP method is a HTTP method that can be called many times without different outcomes. This means that if the request fails on an idempotent request you can retry with the same payload again. However — for a non-idempotent request there is no guarantee that the resource hasn’t been changed. Therefore you must make sure you have the latest resource before doing an non-idempotent request again.

All methods except POST and PATCH are idempotent. The non-safe and non-idempotent methods will never be cached.


Cache headers

It is the responsibility of the server to tell how long a response can be cached. There are different headers for doing this.

Cache-Control

The cache-control header is used to tell other nodes on the internet if this representation can be cached or not. The values no-cache and no-store is commonly used.

The no-cache header value means that the client cannot cache this resource without validating with the server. The no-store header value means that the client cannot store this representation.

Furthermore max-age and public and private is often used. max-age indicates how long the resource can be cached (in seconds) before it is considered stale. public and private can be used to tell other proxy servers if they are allowed to cache the response — only public can be consider safe to cache.

Expires

The expires header is used to tell the client when a resource is considered stale. The value is a HTTP date e.g. Expires: Thu, 01 Dec 1994 16:00:00 GMT.

Validation headers

The server can set two different validation headers on the responses. The first is the weaker one which is called Last-Modified . This tells the client when the resource was last modified. When the client want to validate the resource it can use a conditional header called If-Modified-Since . If the client has the latest resource the server will return a 304 otherwise it returns a fresh resource with the updated validation header Last-Modified . Both headers uses a HTTP date.

The stronger version is called ETAG which is an entity tag. This is an opaque string that the server generate to uniquely identify the freshness of a resource. Again the client can use this to ask if it has the latest version of the resource using the conditional header If-Match . The same pattern is repeated where the server returns a 304 if the client has the latest resource.

The benefit of all this is that the server can skip the serialization step if the client has the latest version already.


Cache proxies

In a typically scenario the clients will talk directly with the application server. The application server is hit on each request to validate the resources.

Clients talk directly to application server

To off-load the application server you can introduce a cache proxy in front. The proxy will then return cached responses where applicable.

A proxy in front of the application server

Conclusion

Good usage of cache headers is an important aspect of API design. Every exposed endpoint needs to be analyzed if it is safe and idempotent and set the correct cache headers accordingly.

Using the HTTP protocol as it is intended lets you benefit from the infrastructure of the world wide web.

Hope this helps!