If you have a website that you want to be able to cache different versions for country, region or city, and you also do not want to run custom VCL due to the multiple pain points this imposes, but you also want simple purging with Acquia Purge, consider using custom Vary headers for caching and purging purposes.
The Vary header is sent by the web server to indicate what makes a HTTP object Vary. This makes a lot of sense with headers like Accept-Encoding. When a server issues a Vary: Accept-Encoding
it tells Varnish that its needs to cache a separate version for every different Accept-Encoding
that is coming from the client. If a client only accepts gzip encoding, Varnish won't serve the version of the page encoded with the Deflate encoding.
Warning!
Acquia Edge does not respect the "Vary" header! You will not be able use this article with it!
If you are using a CDN then you can get these CDN providers to include an extra HTTP header on all requests back to Acquia. You can also add additional custom Vary headers in the response from Drupal. Make sure that your CDN supports the Vary header!
See drupal_add_http_header on the Drupal API. Here is an example that varies on X-MYCUSTOMHEADER
header:
/**
* Implements hook_page_build().
*/
function MYMODULE_page_build(&$page) {
drupal_add_http_header('Vary', 'X-MYCUSTOMHEADER', TRUE);
}
Custom Module
In Drupal 8 use public function HttpResponse::setHeader
along with an event subscriber. Below you can find an example class and services.yml. For a more detailed example please see Event Systems Overview & How To Subscribe To and Dispatch Events.
Warning
Please make sure to replace mymodule_event_subscriber
and MyEventSubscriber
in your own implementation
mymodule_event_subscriber.services.yml
services:
mymodule_event_subscriber:
class: '\Drupal\mymodule_event_subscriber\EventSubscriber\MyVaryEventSubscriber'
tags:
- { name: 'event_subscriber' }
/EventSubscriber/MyVaryEventSubscriber.php
namespace Drupal\mymodule_event_subscriber\EventSubscriber;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Class MyVaryEventSubscriber
*/
class MyVaryEventSubscriber implements EventSubscriberInterface {
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events['kernel.response'] = ['onRespond'];
return $events;
}
/**
* This method is called when the kernel.response is dispatched.
*
* @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
* The dispatched event.
*/
public function onRespond(FilterResponseEvent $event) {
$response = $event->getResponse();
$response->headers->set('Vary', 'X-MYCUSTOMHEADER');
}
}
Contrib Module
The module HTTP Response Headers can also be used to set the Vary header
Acquia's stock VCL (Varnish Configuration Language) in Acquia Cloud means that if a PURGE
request hits (e.g. it matches a variant in cache), or misses (not in cache), purge
is still called. This means all variants will be removed from Varnish immediately. You can also use Acquia Purge.
Warning
Drupal 9 page cache does not respect the Vary header, please ensure that you read Drupal 9 page cache does not respect the Vary header.
Warning
Drupal 7 page cache does not respect the Vary header, please ensure that you read Drupal 7 page cache does not respect the Vary header.
You need to ensure that Drupal is not caching pages for anonymous users (as it will not cache per variant, causing much frustration). See above warnings!
You will also need to be running Acquia's stock VCL with no changes to the vcl_hash()
function (e.g. using geo_ip
functionality), as any alterations to this function will cause a regular PURGE to not remove all variants.
If this content did not answer your questions, try searching or contacting our support team for further assistance.
Wed Oct 22 2025 09:07:31 GMT+0000 (Coordinated Universal Time)