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.
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
PATCH are idempotent. The non-safe and non-idempotent methods will never be cached.
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 header is used to tell other nodes on the internet if this representation can be cached or not. The values
no-store is commonly used.
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.
private is often used.
max-age indicates how long the resource can be cached (in seconds) before it is considered stale.
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 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.
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.
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.
To off-load the application server you can introduce a cache proxy in front. The proxy will then return cached responses where applicable.
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!