Caching and TTL behavior

Thu, Jul 3, 2008 12:56 AM
So, I am working on MemProxy some.  Mainly, I am trying to implement more of the Cache-Control header's many options.  The one that has me a bit perplexed s-maxage.  Particularly when combined with max-age.

s-maxage is the maximum time in seconds an item should remain in a shared cache.  So, if s-maxage is set by the application server, my proxy should keep it for that amount of time at the most.  Up until now, I have just been looking at max-age.  But, s-maxage is the proper one for a proxy to use if it is present.  I do not send the s-maxage through because this is a reverse proxy and, IMO, that is proper behavior for an application accelerating proxy.  However, I do send forward the max-age value that is set by the application servers.  If no max-age is set, I send a default as defined in the script.  Also, if no-cache or no-store is set, I send those and a max-age of 0.

My problem arises when max-age is less than s-maxage.  Up until now, I have sent a max-age back to the client that represents the time left for the cached item in my proxy's cache.  So, if the app server sent back max-age=300 and a request comes in and the cache is found and the cache was created 100 seconds ago, I send max-age-200 back to the client.  But, I was only using max-age before.  Now, in cases where s-maxage is longer than max-age, I would come up with negative numbers.  That is not cool.  The easiest solution would be to always send the original max-age back to the client.  But, that seems kind of lame.

So, my question is, if you are using an application (HTTP or otherwise) accelerator, what would you expect?  If you application set a max-age of 300 would you always expect the end client to receive a max-age of 300?  Or should it count down over time?  The only experience I have is a CDN.  If you watch CDN traffic, the max-age gets smaller and smaller over time until it hits 0.  I have not tried sending an s-maxage to my CDN.  I don't know what they would do with that.  Maybe that is a good test.

UPDATE: Writing this gave me an idea.  If the item will be in the proxy cache longer than the max-age ttl, send the full max-age ttl.  Otherwise, send the time left in the proxy cache.  Thoughts on that?

(thanks for being my teddy bear blogosphere)
Gravatar for Mark Nottingham

Mark Nottingham Says:

In a normal cache (e.g., in a proxy), s-maxage will override max-age as long as it's a shared cache, plain and simple. Such a cache shouldn't modify either of them; instead, it should add to the Age header, as specified.

If you want to hide the fact that you're doing server-side caching, you have to do something else, and you're pretty much on your own (sorry).

Some people who do this will invent a separate freshness mechanism that's targeted just at their cache (e.g., Accelerator-Control). This, however, brings up other problems regarding updating Date and possibly Expires headers, and there are no easy answers here. The cleanest thing to do is to just increment Age and leave it at that.

See also:

Gravatar for Jared

Jared Says:

I'd say you have to revalidate the cache item with the application server, if either max-age or s-maxage are less than 0.

The other option is to use ESI Surrogate-Control header instead of Cache-Control.

Comments are disabled for this post.