Clearing Varnish & Akamai at once?

I’ve got tired of using Luna portal and sending CURL requests to varnish, much like an infomercial there must be a better way…

#Written by spegler on 251114
import requests
import json
from urlparse import urlparse

akamai = ""
akamai_u = "USERNAME HERE"
akamai_p = "PASSWORD HERE"

def main():
    """Clears an item from all available caches."""
    print "Paste in the URL you wish to purge."
    url = raw_input("> ")
    host_header = {"Host": urlparse(url).hostname}
    purge_req =  varnish + urlparse(url).path
    r = requests.request(method="PURGE", url=purge_req, headers=host_header)
    if r.status_code == 200:
        # Even if we get a 200 the item still might not be cleared, check X-Age header.
        res_age = requests.get(url=purge_req, headers=host_header).headers
        if res_age["X-Age"] >= 5:
            vresult = "Varnish: Item Cleared."
            vresult = "Varnish: Accepted request but item age is still old. Age is: %s" % res_age["X-Age"]
        vresult = "Varnish: I'm sorry, Dave. I'm afraid I can't do that."
        # This is normally down to a Varnish ACL error.
    # Setup payload as a json object list.
    payload = json.dumps({"objects": [url]})
    # Post out to Akamai.
    a =, auth=(akamai_u, akamai_p), headers={"Content-Type":"application/json"}, data=payload)
    # It would probably be a good idea to add a little more error checking on this, but a 200 out of Akamai should be good enough.
    if a.status_code == 201:
        aresult = "Akamai: Item cleared."
        aresult = "Akamai: I think we should stop."

    return vresult + " " + aresult

if __name__ == "__main__":
    print main()

Change the global variables at the top and you should be good to go. This probably needs some logging, but I’ll add that later. Thinking about it pushing it to a full django app wouldn’t take too long. You can watch progress on…


Varnish Grace Debugging.

I love Varnish. As far as the world of HTTP goes, in environments where you can cache, I think it’s the most important piece of software bar none. However, this somewhat comes at a price, as often you’ll sit back and your box of magic doesn’t produce entirely the result you expect it. I add a bunch of HTTP headers to requests as they pass through for debugging. One of these I add is X-Grace, to show me if Varnish thinks it served a graced object.

To start with you need to add a header in VCL receive, this ensures that all requests get the header. If this wasn’t added and the request was made, if it was a cache miss no header would be appended.

sub vcl_recv {

        ## Set default grace header ##
        set req.http.X-Grace = "First Hit";
        ## Rest of recv goes here... ##
        return (hash);

You could probably add this in vcl_miss if you wanted to, there may be a tiny overhead in adding it to all requests in receive, but I’ve seen no effect on loads of up to 10k/s.

To check the status of the object, we need to peer in via VCL hit.

sub vcl_hit {

        ## Deliver if fresh. ##
        if (obj.ttl >= 0s) {
                set req.http.X-Grace = "Fresh Hit";
                return (deliver);

        ## Check if backend is healthy ##
        if (std.healthy(req.backend_hint)) {
            if (obj.ttl + 20s > 0s) {
                set req.http.X-Grace = "Stale Hit";
                return (deliver);
            else {
                return (fetch);
        } else {
            if (obj.ttl + obj.grace > 0s) {
                set req.http.X-Grace = "Rotten Hit";
                return (deliver);
            } else {
                return (fetch);
    return (deliver);

This is fairly simple, one if statement followed by an if else statement. Initially we check if the object, if it is, we deliver it. Else, we check to see if the backend is healthy. If it is, and object is just stale, we return the object and fetch another (hooray for async fetches in v4). If the backend is not healthy, we try to deliver a stale object rather than nothing. If nothing is available we try to fetch, and will eventually serve a 503.

sub vcl_deliver {
    set resp.http.X-Grace = req.http.X-Grace;

Needs to be added to VCL deliver to copy the header across from into our response.

If any of this unclear, theres an official Varnish article available here…