Varnish expires header configuration

Please help me in adding expires header in varnish configuration. max_age is already defined in vcl_fetch and need to add expires header according to the max_age.


Usually you do not need to set Expires header in addition to Cache-Control. The Expires header tells the cache (be it a proxy server or a browser cache) to cache the file until Expires time is reached. If both Cache-Control and Expires are defined, Cache-Control takes precedence.

Consider the following response header:

HTTP/1.1 200 OK
Content-Type: image/jpeg
Date: Fri, 14 Mar 2014 08:34:00 GMT
Expires: Fri, 14 Mar 2014 08:35:00 GMT
Cache-Control: public, max-age=600

According to Expires header the content should be refreshed after one minute, but since max-age is set to 600 seconds, the image stays cached until 08:44:00 GMT.

If you wish to expire content at a specific time, you should drop the Cache-Control header and only use Expires.

Mark Nottingham has written a very good tutorial on caching. It's definitely worth reading when considering your cache strategy.

If you wish to set Expires header based on Cache-Control: max-age, you need to use inline-C in your VCL. The following is copied from in case the page is removed in the future.

Add the following prototypes:

        #include <string.h>
        #include <stdlib.h>

        void TIM_format(double t, char *p);
        double TIM_real(void);

And the following piece of inline-C to the vcl_deliver function:

        char *cache = VRT_GetHdr(sp, HDR_RESP, "\016cache-control:");
        char date[40];
        int max_age = -1;
        int want_equals = 0;
        if(cache) {
                while(*cache != '\0') {
                        if (want_equals && *cache == '=') {
                                max_age = strtoul(cache, 0, 0);

                        if (*cache == 'm' && !memcmp(cache, "max-age", 7)) {
                                cache += 7;
                                want_equals = 1;
                if (max_age != -1) {
                        TIM_format(TIM_real() + max_age, date);
                        VRT_SetHdr(sp, HDR_RESP, "\010Expires:", date, vrt_magic_string_end);

Assuming max-age is already setted (i.e by your webserver), you can set Expires header with this configuration in your vcl :

# Add required lib to use durations
import std;

sub vcl_backend_response {

    # If max-age is setted, add a custom header to delegate calculation to vcl_deliver
    if (beresp.ttl > 0s) {
        set beresp.http.x-obj-ttl = beresp.ttl + "s";


sub vcl_deliver {

    # Calculate duration and set Expires header
    if (resp.http.x-obj-ttl) {
        set resp.http.Expires = "" + (now + std.duration(resp.http.x-obj-ttl, 3600s));
        unset resp.http.x-obj-ttl;

Source :

Additional info : you can set max-age on your apache server with this example :

<LocationMatch "/(path1|path2)/">
    ExpiresActive On
    ExpiresDefault "access plus 1 week"

Need Your Help

Multiple Render Targets in OpenGL with Cg

opengl framebuffer shader cg render-to-texture

I'm trying (in vain) to set up MRT using OpenGL and NVIDIA's Cg shader system, with the ultimate goal of deferred rendering. I've successfully gotten both shaders and Render To Texture for single t...

To bless or not to bless, that is my question!

perl oop class bless

first post from a newbie-user. Every question I google seems to bring me here and I always get a great answer to what I'm looking for; so naturally this was my first stop when I began pondering the...