The built-in vcl_pass subroutine is executed when pass is returned by the vcl_recv, vcl_miss, or vcl_hit subroutines.

The subroutines vcl_pass and vcl_miss are very similar in nature. They both run immediately prior to a backend fetch, usually on a fetch node. In preparation for making a request to the backend, a copy of the client request is created, and is available as bereq. This backend request object is writable, and any changes made to it do not affect the state of the client request, nor the cache address in which the response may be stored. This is therefore a good opportunity to remove any headers that you do not wish to send to the backend or to add authentication data required by the backend.

Key use cases:

  • Preparing request headers for a specific origin/backend.
  • Adding authentication requirements when the origin is a private bucket at AWS S3, GCS or similar.
  • Unsetting request headers that are being used internally in VCL and are not required at origin.

The vcl_pass subroutine should return(pass) to start the backend fetch. error may be used in vcl_pass but it is not possible to restart the request from here.

If vcl_pass is invoked due to return(pass) in vcl_recv, it will execute on the delivery node. If it is triggered by return(pass) in vcl_hit or vcl_miss, it may instead run on a fetch node as a result of clustering.

Using a 'prefetch' custom subroutine

Since it is common for vcl_miss and vcl_pass to perform broadly the same tasks, it is often useful to create a custom subroutine and invoke it from both places:

sub miss_pass {
# Common logic goes here
sub vcl_pass {
#FASTLY pass
call miss_pass;
sub vcl_miss {
#FASTLY miss
call miss_pass;

State transitions


To see this subroutine in the context of the full VCL flow, see using VCL.

Tokens available in this subroutine

The following limited-scope VCL functions and variables are available for use in this subroutine (those in bold are available only in this subroutine, those available in *all* subroutines are not listed):