Nginx – Deleting key in Nginx cache and Backend database in the same request

cachenginxopenrestyreverse-proxyvarnish

I am using the open source Nginx as the web server with Proxy_cache.

I have a unique usecase of deleting the key in cache as well as pass the request to the backend servers to delete the key in DB without caching the response.

So delete key in Web server cache and backend DB in same request.
Client => load balancer => Nginx(proxy_cache) => application => PostgreSQL

e.g Nginx.conf

if ( $http_x_delete_key ){
  content_by_lua_file ./purge_key.lua;
  proxy_pass          http://backend_servers; 
}

e.g purge_key.lua

...
if ngx ~= nil then
    ...
    delete_file(filename)
    ngx.log(ngx.NOTICE, 'deleted')
    -- ngx.exit(ngx.OK);
    -- return
end

The 'if' block in Nginx location section just stops the flow (How nginx "location if" works) and returns the response without sending it to the backend and is not passing the request as it is.
I have even compiled OpenResty using the free 'ngx_cache_purge' module but the purge command also doesn't pass the request to the backend.

Generally you timeout or refresh the key using the backend response but in my case I need more explicit control to delete the key either in the same request or it's response.

Does Openresty+Memcache, Apache httpd, Apache Traffic Server or Varnish (vcl_purge and pass) solve this usecase or is there some other way to do it?

Best Answer

I have kind of found a way to do this.

Depending on the HTTP request header value, run a lua script to delete the cache file (hash of key and it's last x+y characters if x:y cache level) in Nginx's proxy_cache.

Using 'access_by_lua' instead of 'content_by_lua' as the content handler phase will always exit and return even if I don't write 'ngx.exit' or 'ngx.OK'.

I have to run the lua script in the NGX_HTTP_ACCESS_PHASE and not in the NGX_HTTP_CONTENT_PHASE as I am not generating content or response which should come from the backend in my scenario.

e.g Nginx.conf

proxy_cache_bypass     $http_x_delete_key;
proxy_no_cache         $http_x_delete_key;

if ( $http_x_delete_key ){
  ...
  access_by_lua_file ./purge_key.lua;
}

When the delete key request comes, Nginx will
1. Run the lua script to delete cache file but not return immediately as it's in access phase
2. Request will bypass the cache
3. Upon receiving the request the application will delete key in the DB
4. The response will not be cached in Nginx proxy_cache