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:

RECVHASHHITPASSMISSFETCHERRORDELIVERLOGFetch nodeDefault pathAlternative pathErrorRestartRequest to origin
NameTrigger pointDefault return stateAlternative return states
vcl_recvClient request receivedlookuprecv-notepass, error, restart, upgrade
vcl_hashA cache key will be calculatedhash hash-note
vcl_hitAn object has been found in cachedeliverpass, error, restart
vcl_missNothing was found in the cache, preparing backend fetchfetchdeliver_stale, pass, error
vcl_passCache bypassed, preparing backend fetchpass pass-noteerror
vcl_fetchOrigin response headers receiveddeliver fetch-notedeliver_stale, pass, error, restart
vcl_errorError triggered (explicitly or by Fastly)deliverrestart
vcl_deliverPreparing to deliver response to clientdeliverrestart
vcl_logFinished sending response to clientdeliverlog-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).


  1. The return state from vcl_log simply terminates request processing.
  2. Returning with return(deliver) from vcl_fetch cannot override an earlier pass, but return(pass) here will prevent the response being cached.
  3. The return(pass) exit from vcl_pass triggers a backend fetch, similarly to return(fetch) in vcl_miss but the altered return state is a reminder that the object is flagged for pass, so that it cannot be cached when processed in vcl_fetch.
  4. The only possible return state from vcl_hash is hash but it will trigger different behavior depending on the earlier return state of vcl_recv. The default return(lookup) in vcl_recv will prompt Fastly to perform a cache lookup and run vcl_hit or vcl_miss after hash. If vcl_recv returns error, then vcl_error is executed after hash. If vcl_recv returns return(pass), then vcl_pass is executed after hash. The hash process is required in all these cases to create a cache object to enable hit-for-pass.
  5. All return states from vcl_recv (except restart) pass through vcl_hash first. return(lookup) and return(pass) both move control to vcl_hash but flag the request differently, which will determine the exit state from vcl_hash.