VCL request lifecycle
VCL does not run like a traditional program with a single entry point for your code. Instead, Fastly exposes built-in subroutines as hooks that execute at significant moments during each HTTP request's lifecycle. These hooks are where you can add your code.
This approach means your uploaded code functions as a configuration rather than a standalone application. Changes to your VCL can be generated automatically through the Fastly control panel, compiled, and distributed to all Fastly caches worldwide, all without requiring maintenance windows or service downtime.
Here are the main subroutines, in the order they run:
| Name | Trigger point | Default return state | Alternative return states |
|---|---|---|---|
vcl_recv | Client request received | lookuprecv-note | pass, error, restart, upgrade |
vcl_hash | A cache key will be calculated | hash hash-note | |
vcl_hit | An object has been found in cache | deliver | pass, error, restart |
vcl_miss | Nothing was found in the cache, preparing backend fetch | fetch | deliver_stale, pass, error |
vcl_pass | Cache bypassed, preparing backend fetch | pass pass-note | error |
vcl_fetch | Origin response headers received | deliver fetch-note | deliver_stale, pass, error, restart |
vcl_error | Error triggered (explicitly or by Fastly) | deliver | restart |
vcl_deliver | Preparing to deliver response to client | deliver | restart |
vcl_log | Finished sending response to client | deliverlog-note |
Some subroutines can return error, restart, or upgrade. Any error return state will result in the execution flow passing to vcl_error, while restart will result in the execution flow passing to vcl_recv. The special upgrade return state will terminate the VCL flow and create a managed WebSocket connection (learn more).
- The return state from
vcl_logsimply terminates request processing.↩ - Returning with
return(deliver)fromvcl_fetchcannot override an earlier pass, butreturn(pass)here will prevent the response being cached.↩ - The
return(pass)exit fromvcl_passtriggers a backend fetch, similarly toreturn(fetch)invcl_missbut the altered return state is a reminder that the object is flagged for pass, so that it cannot be cached when processed invcl_fetch.↩ - The only possible return state from
vcl_hashishashbut it will trigger different behavior depending on the earlier return state ofvcl_recv. The defaultreturn(lookup)invcl_recvwill prompt Fastly to perform a cache lookup and runvcl_hitorvcl_missafter hash. Ifvcl_recvreturnserror, thenvcl_erroris executed after hash. Ifvcl_recvreturnsreturn(pass), thenvcl_passis executed after hash. The hash process is required in all these cases to create a cache object to enable hit-for-pass.↩ - All return states from
vcl_recv(exceptrestart) pass throughvcl_hashfirst.return(lookup)andreturn(pass)both move control tovcl_hashbut flag the request differently, which will determine the exit state fromvcl_hash.↩