About Fastly VCL

Fastly VCL is a domain-specific programming language that evolved from the Varnish proxy cache, forming a core part of Fastly's platform architecture. The Varnish Configuration Language (VCL) is intentionally limited in scope so that it can run quickly, maintain strong security, and be applied consistently to every request passing through Fastly.

With VCL you can handle everything from simple tasks like setting Cache-Control headers, to building advanced implementations like authentication flows or full paywall systems.

VCL and what you can do with it

Every Fastly service runs on VCL, even when you don't write any code yourself. Each time you configure features in the web interface or via the API, Fastly translates those configuration settings automatically into generated VCL.

You aren't limited to using just generated VCL however. You can mix and match your code with the generated VCL, using them together to create specialized configurations. Your code customizations can modify and extend Fastly's own generated logic. Keep in mind, however, that VCL code you create always takes precedence over any VCL generated by the control panel.

IMPORTANT:

Personal data should not be incorporated into VCL. Our Compliance and Law FAQ describes in detail how Fastly handles personal data privacy.

Ways to add VCL code to service configurations

You can add custom behavior to your services in three ways, each of which you can mix and match to create specialized configurations:

  • via VCL generative objects, features you configure using the Fastly control panel's web interface or the API
  • via VCL snippets, short blocks of code you attach to subroutines in generated VCL
  • via custom VCL, a full VCL file that you upload to replace the one Fastly generates

To make all three methods work together, Fastly uses macros inside each subroutine. Macros (for example, #FASTLY recv) act as placeholders where Fastly inserts generated code and snippets during compilation. If you remove them, Fastly cannot insert its generated logic, and your service may fail to compile.

VCL generative objects

Generative objects let you configure behavior without writing code. Fastly turns them into VCL automatically, which you can review by accessing the Complete VCL tab from the VCL section of a service's configuration. However, you can't edit this generated VCL. You can only make changes to these objects via the web interface or API.

ObjectPurposeDocs
HeaderSetting HTTP headers or VCL variablesWeb interface, API
ResponseCreating a predefined response to be served from the edgeWeb interface, API
ConditionRestricting actions to only requests that meet criteria defined as a VCL expressionWeb interface, API
Apex redirectRedirecting a bare domain such as example.com to add a www. prefixAPI
Cache settingsChanging the TTL or cache behavior of an HTTP responseWeb interface, API
GZipCompressing HTTP responses before inserting them into cacheWeb interface, API
HTTP/3Advertising HTTP/3 supportWeb interface
Rate limiterCreating rate limiters to stop individual clients from bombarding your siteWeb interface, API
Request settingsChanging the cache behavior of a request (similar to a cache setting but applied before the request has been forwarded to origin)Web interface, API
SettingsUpdate default values for cache TTLsAPI

HINT: Generative objects are a good starting point for learning how to customize VCL for your service configurations. If your configuration becomes crowded with many of those objects, however, it may be easier to use custom VCL to manage things.

VCL snippets

VCL snippets are short blocks of VCL logic that extend or modify the default Fastly-generated configuration. They are most useful when you want to make targeted changes to your service's settings because they don't require you to replace the generated VCL.

Snippets come in two types:

  • Regular snippets: used for procedural logic such as setting headers, routing requests, or applying access controls.
  • Dynamic snippets: used for inserting generated rules or structured data such as redirects or allowlists. (If possible, use a dictionary instead, since it is easier to manage.)

If you have VCL snippets defined on a service that also has custom VCL, the snippets will typically be rendered inside of the Fastly macros, replacing the placeholders that you must include in any custom VCL file.

Snippets can be included as many times and in as many places as desired, subject to compiler rules. For example, if your snippet attempts to set bereq.http.cookie you cannot include that snippet in the vcl_recv subroutine, because bereq is not available in the vcl_recv scope. Our guide to VCL variables contains more details.

Custom VCL

Custom VCL allows you to upload a full VCL source file to entirely replace the one that would otherwise be generated by Fastly. To make sure that features you create using VCL generative objects still work, we require that custom VCL files include Fastly's macros, one in each subroutine.

We recommend starting your custom VCL file with Fastly's boilerplate. It includes all the required Fastly macro placeholders and also presents VCL subroutines in the order in which they are executed.

sub vcl_recv {
#FASTLY recv
# Normally, you should consider requests other than GET and HEAD to be uncacheable
# (to this we add the special FASTLYPURGE method)
if (req.method != "HEAD" && req.method != "GET" && req.method != "FASTLYPURGE") {
return(pass);
}
# If you are using image optimization, insert the code to enable it here
# See https://www.fastly.com/documentation/reference/io/ for more information.
return(lookup);
}
sub vcl_hash {
set req.hash += req.url;
set req.hash += req.http.host;
#FASTLY hash
return(hash);
}
sub vcl_hit {
#FASTLY hit
return(deliver);
}
sub vcl_miss {
#FASTLY miss
return(fetch);
}
sub vcl_pass {
#FASTLY pass
return(pass);
}
sub vcl_fetch {
#FASTLY fetch
# Unset headers that reduce cacheability for images processed using the Fastly image optimizer
if (req.http.X-Fastly-Imageopto-Api) {
unset beresp.http.Set-Cookie;
unset beresp.http.Vary;
}
# Log the number of restarts for debugging purposes
if (req.restarts > 0) {
set beresp.http.Fastly-Restarts = req.restarts;
}
# If the response is setting a cookie, make sure it is not cached
if (beresp.http.Set-Cookie) {
return(pass);
}
# By default we set a TTL based on the `Cache-Control` header but we don't parse additional directives
# like `private` and `no-store`. Private in particular should be respected at the edge:
if (beresp.http.Cache-Control ~ "(?:private|no-store)") {
return(pass);
}
# If no TTL has been provided in the response headers, set a default
if (!beresp.http.Expires && !beresp.http.Surrogate-Control ~ "max-age" && !beresp.http.Cache-Control ~ "(?:s-maxage|max-age)") {
set beresp.ttl = 3600s;
# Apply a longer default TTL for images processed using Image Optimizer
if (req.http.X-Fastly-Imageopto-Api) {
set beresp.ttl = 2592000s; # 30 days
set beresp.http.Cache-Control = "max-age=2592000, public";
}
}
return(deliver);
}
sub vcl_error {
#FASTLY error
return(deliver);
}
sub vcl_deliver {
#FASTLY deliver
return(deliver);
}
sub vcl_log {
#FASTLY log
}

Where to learn more about VCL and Varnish

Fastly provides a VCL reference for programming custom logic on VCL services along with guides on using VCL and the current best practices. These resources focus on how VCL works within the Fastly platform.

For background information on the language itself, the official Varnish documentation is a good online starting point. Varnish Software, which provides commercial support for Varnish, also maintains a free online book covering more technical details.