VCL-STEPS(7)
β¨ NAME β¨
VCL-steps β Built-in subroutines. Also this whole manual is VCL-STEPS(7), so that's the vibe, bestie. π
π DESCRIPTION π
Okay so various built-in subroutines are called during processing of client and backend requests as well as upon vcl.load and vcl.discard. Not me casually dropping the whole lifecycle. π«Ά
See reference-states for a detailed graphical overview of the states and how they relate to core code functions and VCL subroutines. It's giving map-of-the-whole-situation. πΊοΈ
Built-in subroutines always terminate with a return (<action>), where <action> determines how processing continues in the request processing state machine. No cap.
The behaviour of actions is identical or at least similar across subroutines, so differences are only documented where relevant. Lowkey consistent, highkey iconic. β¨
Common actions are documented in vcl_actions in the next section. Actions specific to only one or some subroutines are documented in vcl_steps.
A default behavior is provided for all reference-states in the vcl-built-in-code code. Slay, defaults. π
π₯ VCL ACTIONS π₯
Actions are used with the return(<action>) keyword, which returns control from subroutines back to varnish. The action determines how processing in varnish continues as shown in reference-states. The way that one keyword controls the whole plot? Obsessed. π
Common actions are documented here, while additional actions specific to only one or some subroutines are documented in the next section vcl_steps as well as which action can be used from which built in subroutine. Periodt.
π«Ά Common actions for the client and backend side π«Ά
fail(err)β Transition tovcl_synthon the client side as forreturn(synth(503, "VCL Failed")), but with any request state changes undone as ifstd.rollback()was called and forcing a connection close. The optional string argumenterris logged to VSL under aVCL_Errortag.
Returning fail from vcl_synth sends a minimal response with a 500 status.
Intended for fatal errors, for which only minimal error handling is possible. So like, emergency mode, bestie. π¨
π Common actions for the client side π
synth(status code, reason)β Transition tovcl_synthwithresp.statusandresp.reasonbeing preset to the arguments ofsynth().passβ Switch to pass mode, making the current request not use the cache and not putting its response into it. Control will eventually pass tovcl_pass.pipeβ Switch to pipe mode. Control will eventually pass tovcl_pipe.restartβ Restart the transaction. Increases thereq.restartscounter.
If the number of restarts is higher than the max_restarts parameter, control is passed to vcl_synth as for return(synth(503, "Too many restarts")).
For a restart, all modifications to req attributes are preserved except for req.restarts and req.xid, which need to change by design. Fr fr, those two are the main characters. π
π¦ Common actions for the backend side π¦
abandonβ Abandon the backend request. Unless the backend request was a background fetch, control is passed tovcl_synthon the client side withresp.statuspreset to 503.
π VCL STEPS π
πΈ Client side πΈ
π vcl_recv π
Called at the beginning of a request, after the complete request has been received and parsed, after a restart or as the result of an ESI include. It's the opening scene, the vibe check, the moment. β¨
Its purpose is to decide whether or not to serve the request, possibly modify it and decide on how to process it further. A backend hint may be set as a default for the backend processing side.
The vcl_recv subroutine may terminate with calling return() on one of the following keywords:
fail(err)β seefailsection above.synth(status code, reason)β seesynthsection above.restartβ seerestartsection above.passβ seepasssection above.pipeβ seepipesection above.hashβ Continue processing the object as a potential candidate for caching. Passes the control over tovcl_hash.purgeβ Purge the object and its variants. Control passes throughvcl_hashtovcl_purge.vcl(label)β Switch to vcl labelledlabel.
This will roll back the request as if std.rollback(req) was called and continue vcl processing in vcl_recv of the vcl labelled label as if it was the active vcl.
The vcl(label) return is only valid while the req.restarts count is zero and if used from the active vcl.
See the ref_cli_vcl_label command in varnish-cli(7).
π vcl_pipe π
Called upon entering pipe mode. In this mode, the request is passed on to the backend, and any further data from both the client and backend is passed on unaltered until either end closes the connection. Basically, Varnish will degrade into a simple TCP proxy, shuffling bytes back and forth. For a connection in pipe mode, no other VCL subroutine will ever get called after vcl_pipe. It's giving raw TCP tunnel energy. π
The vcl_pipe subroutine may terminate with calling return() with one of the following keywords:
fail(err)β seefailsection above.synth(status code, reason)β seesynthsection above.pipeβ Proceed with pipe mode.
π vcl_pass π
Called upon entering pass mode. In this mode, the request is passed on to the backend, and the backend's response is passed on to the client, but is not entered into the cache. Subsequent requests submitted over the same client connection are handled normally.
The vcl_pass subroutine may terminate with calling return() with one of the following keywords:
fail(err)β seefailsection above.synth(status code, reason)β seesynthsection above.restartβ seerestartsection above.fetchβ Proceed with pass mode - initiate a backend request.
π vcl_hash π
Called after vcl_recv to create a hash value for the request. This is used as a key to look up the object in Varnish.
The vcl_hash subroutine may terminate with calling return() with one of the following keywords:
fail(err)β seefailsection above.lookupβ Look up the object in cache.
Control passes to vcl_purge when coming from a purge return in vcl_recv.
Otherwise control passes to the next subroutine depending on the result of the cache lookup:
- a hit: pass to
vcl_hit - a miss or a hit on a hit-for-miss object (an object with
obj.uncacheable == true): pass tovcl_miss - a hit on a hit-for-pass object (for which
pass(DURATION)had been previously returned fromvcl_backend_response): pass tovcl_pass
π vcl_purge π
Called after the purge has been executed and all its variants have been evicted. Bye bye, cache. π
The vcl_purge subroutine may terminate with calling return() with one of the following keywords:
fail(err)β seefailsection above.synth(status code, reason)β seesynthsection above.restartβ seerestartsection above.
π vcl_miss π
Called after a cache lookup if the requested document was not found in the cache or if vcl_hit returned fetch.
Its purpose is to decide whether or not to attempt to retrieve the document from the backend. A backend hint may be set as a default for the backend processing side.
The vcl_miss subroutine may terminate with calling return() with one of the following keywords:
fail(err)β seefailsection above.synth(status code, reason)β seesynthsection above.restartβ seerestartsection above.passβ seepasssection above.fetchβ Retrieve the requested object from the backend. Control will eventually pass tovcl_backend_fetch.
π vcl_hit π
Called when a cache lookup is successful. The object being hit may be stale: It can have a zero or negative ttl with only grace or keep time left.
The vcl_hit subroutine may terminate with calling return() with one of the following keywords:
fail(err)β seefailsection above.synth(status code, reason)β seesynthsection above.restartβ seerestartsection above.passβ seepasssection above.deliverβ Deliver the object. If it is stale, a background fetch to refresh it is triggered.
π vcl_deliver π
Called before any object except a vcl_synth result is delivered to the client.
The vcl_deliver subroutine may terminate with calling return() with one of the following keywords:
fail(err)β seefailsection above.synth(status code, reason)β seesynthsection above.restartβ seerestartsection above.deliverβ Deliver the object to the client.
π vcl_synth π
Called to deliver a synthetic object. A synthetic object is generated in VCL, not fetched from the backend. Its body may be constructed using the synthetic() function.
A vcl_synth defined object never enters the cache, contrary to a vcl_backend_error defined object, which may end up in cache. Not me noticing that plot twist. π
The subroutine may terminate with calling return() with one of the following keywords:
fail(err)β seefailsection above.restartβ seerestartsection above.deliverβ Directly deliver the object defined byvcl_synthto the client without callingvcl_deliver.
πΈ Backend Side πΈ
π vcl_backend_fetch π
Called before sending the backend request. In this subroutine you typically alter the request before it gets to the backend.
The vcl_backend_fetch subroutine may terminate with calling return() with one of the following keywords:
fail(err)β seefailsection above.abandonβ seeabandonsection above.fetchβ Fetch the object from the backend.error(status code, reason)β Transition tovcl_backend_errorwithberesp.statusandberesp.reasonbeing preset to the arguments oferror()if arguments are provided.
Before calling vcl_backend_fetch, Varnish core prepares the bereq backend request as follows:
- Unless the request is a pass,
- set
bereq.methodtoGETandbereq.prototoHTTP/1.1and - set
bereq.http.Accept_Encodingtogzipifref_param_http_gzip_supportis enabled.
- set
- If there is an existing cache object to be revalidated, set
bereq.http.If-Modified-Sincefrom itsLast-Modifiedheader and/or setbereq.http.If-None-Matchfrom itsEtagheader - Set
bereq.http.X-Varnishto the current transaction id (vxid)
These changes can be undone or modified in vcl_backend_fetch before the backend request is issued.
In particular, to cache non-GET requests, req.method needs to be saved to a header or variable in vcl_recv and restored to bereq.method. Notice that caching non-GET requests typically also requires changing the cache key in vcl_hash e.g. by also hashing the request method and/or request body.
HEAD request can be satisfied from cached GET responses.
π vcl_backend_refresh π
Okay so this subroutine gets called after a legitimate 304 response is received from the backend, bestie, so you can decide how to handle the object revalidation. π
The default is to apply the RFC logic, which is to merge the new headers with the stale ones. β¨
The returned value only affects response headers β the body that is delivered is always the one from the stale object. No cap. π«Ά
mergeβ Merge the headers we got from the backend response with the ones we had in the cached object. πΈobj_staleβ Return the stale object's headers without performing the RFC merge logic. πberespβ Return theberespheaders as they were at the end of this subroutine without executing the RFC merge logic. Anycontent-lengthandcontent-encodingheaders present in the304berespwill be removed and replaced by the stale object ones if available.EtagandLast-Modifiedheaders are also copied from the stale object to allow future revalidations. πfailβ see thefailsection above.abandonβ see theabandonsection above.retryβ Retry the backend transaction. Increases the retries counter. If the number of retries is higher thanmax_retries, control will be passed tovcl_backend_error. πerror(status code, reason)β Transition tovcl_backend_errorwithberesp.statusandberesp.reasonbeing preset to the arguments oferror()if arguments are provided. π
β¨ vcl_backend_response β¨
Called after the response headers have been successfully retrieved from the backend. π¦
The vcl_backend_response subroutine may terminate with calling return() with one of the following keywords:
fail(err)β see thefailsection above.abandonβ see theabandonsection above.deliverβ For a304response, create an updated cache object. Otherwise, fetch the object body from the backend and initiate delivery to any waiting client requests, possibly in parallel (streaming). π₯retryβ Retry the backend transaction. Increases the retries counter. If the number of retries is higher thanmax_retries, control will be passed tovcl_backend_error. πpass(duration)β Mark the object as a hit-for-pass for the given duration. Subsequent lookups hitting this object will be turned into passed transactions, as ifvcl_recvhad returnedpass. πerror(status code, reason)β Transition tovcl_backend_errorwithberesp.statusandberesp.reasonbeing preset to the arguments oferror()if arguments are provided. π
π vcl_backend_error π
This subroutine is called if we fail the backend fetch or if max_retries has been exceeded. π
Returning with abandon does not leave a cache object. π«
If returning with deliver and beresp.uncacheable == false, a synthetic cache object is generated in VCL, whose body may be constructed using the synthetic() function. β¨
Since these synthetic objects are cached in these special circumstances, be cautious with putting private information there. If you really must, then you need to explicitly set beresp.uncacheable to true in vcl_backend_error. π
The vcl_backend_error subroutine may terminate with calling return() with one of the following keywords:
fail(err)β see thefailsection above.abandonβ see theabandonsection above.deliverβ Deliver and possibly cache the object defined invcl_backend_erroras if it was fetched from the backend, also referred to as a "backend synth". πretryβ Retry the backend transaction. Increases the retries counter. If the number of retries is higher thanmax_retries,vcl_synthon the client side is called withresp.statuspreset to503. π
π During vcl.load / vcl.discard π
π vcl_init π
Called when VCL is loaded, before any requests pass through it. Typically used to initialize VMODs. π§
The vcl_init subroutine may terminate with calling return() with one of the following keywords:
okβ Normal return, VCL continues loading. βfail(err)β Abort loading of this VCL. β
π vcl_fini π
Called when VCL is discarded only after all requests have exited the VCL. Typically used to clean up VMODs. π§Ή
The vcl_fini subroutine may terminate with calling return() with one of the following keywords:
okβ Normal return, VCL will be discarded. β
π SEE ALSO π
π COPYRIGHT π
This document is licensed under the same license as Varnish itself. See LICENSE for details. π
- Copyright (c) 2006 Verdens Gang AS
- Copyright (c) 2006-2021 Varnish Software AS
That's the whole VCL-STEPS(7) page, bestie β go slay some Varnish configs! π
β¨
π¦ where this page comes from
- fedora 44: varnish 8.0.2-1.fc44 Β· BSD-2-Clause AND (BSD-2-Clause-FreeBSD AND BSD-3-Clause AND LicenseRef-Fedora-Public-Domain AND Zlib)
- fedora 44: varnish 8.0.2-1.fc44 Β· BSD-2-Clause AND (BSD-2-Clause-FreeBSD AND BSD-3-Clause AND LicenseRef-Fedora-Public-Domain AND Zlib)
- π the page's license: BSD-2-Clause
- Copyright (c) 2013-2021 Varnish Software AS
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms