Web

What Is Varnish Cache and How Do You Install It?

Talha Aslan 19 min read 2 views

What is Varnish Cache?

Varnish Cache is an open source HTTP reverse proxy cache that sits in front of your web server. It also stores finished page responses in memory and serves repeat requests directly, without waking up your application, PHP, or database. As a result, server load drops, response times shrink, and your site handles traffic spikes more calmly.

We wrote this guide for site owners, store owners, developers, and anyone who runs their own VPS. We are a digital marketing and web team, not a hosting company. So we based every explanation on the official Varnish documentation and on HTTP standards. Before you run any command on a live system, compare it with the documentation for your own distribution.

What problem does Varnish Cache solve for your website?

A dynamic page runs application code on every visit, queries the database, and builds HTML from scratch. If a thousand people ask for the same page, you do the same work a thousand times. So Varnish cuts that repetition. It forwards the first request to the backend, stores the answer, and serves later requests from its own memory.

This brings three concrete benefits. First, response time improves, because an answer from memory never waits for the application layer. Second, resilience improves, since the backend sees far fewer simultaneous requests during a campaign. Third, you scale further, because you get more out of your current server before you buy a bigger one.

We covered the search side of speed in our guide on how site speed affects SEO. In that chain, Varnish only improves server response time. Also, it does not fix heavy images, JavaScript, or fonts.

How does Varnish work, and what path does a request take?

The visitor's request reaches Varnish first. Varnish turns the request into a lookup key, and by default that key is built from the host name and the URL. If the key exists in memory, that is a "hit" and the answer returns immediately. If not, it is a "miss" and Varnish passes the request to the backend server.

When the backend answers, Varnish keeps the response for a set time. The backend usually sets that time through the Cache-Control header. For the standard definition of HTTP caching rules, read RFC 9111.

  1. The visitor asks for a page, and the request reaches Varnish.
  2. Varnish looks for a matching object in its cache.
  3. If it finds one, it returns the response at once (a hit).
  4. If it finds none, it sends the request to the backend (a miss).
  5. The backend answers, Varnish stores the response, and then it delivers it to the visitor.

In practice, a configuration language called VCL controls this flow. It decides which requests enter the cache, which ones bypass it, and how long objects stay.

Keep one detail in mind: a cached response stays the same until it expires or you purge it. So after you update content, seeing the old page for a while is a normal result. We will manage that behavior in the purge section below.

What is the difference between Varnish, Redis, and OPcache?

People call all three "caches," but they work at different layers and do not replace each other. First, Varnish stores the complete HTTP response. Second, Redis holds data that your application produced. Finally, OPcache keeps compiled PHP code in memory. On many sites, all three run together.

LayerWhat it storesWhere it runsWho benefits most
VarnishReady-made HTTP response (full page)In front of the web serverSites with heavy anonymous traffic
RedisApplication data, sessions, query resultsNext to the applicationDynamic apps that read data often
OPcacheCompiled PHP bytecodeInside the PHP processEvery PHP site

We explain the Redis and Memcached split in detail in our guide on how caching works, so we will not repeat it here. The table already tells you the key point: Varnish works outside the application, at the outermost layer.

When does Varnish Cache help, and when does it not?

Varnish shines on sites where most visitors see the same content. For example, news sites, blogs, corporate sites, and product listing pages fit well. If a page does not change per person, the hit rate rises and the gain is clear.

On the other hand, pages that build unique content for each visitor gain much less. A logged-in dashboard, a cart, and a checkout step are good examples. We will cover how to bypass those pages later.

  • Good fit: Pages that people read often, that rarely change, and that look the same to everyone.
  • Limited benefit: Low traffic sites, because an extra layer in front of an already fast page adds little.
  • Poor fit: Personalized, session based, or constantly changing content.
  • Keep in mind: A slow first request (a miss) does not get faster with Varnish.

What should you prepare before you install Varnish?

Before you install Varnish, you need to know your current stack. Is your web server Nginx or Apache, which port does it use, and where does HTTPS end? So these three answers shape the rest of the setup.

  • A test environment: Rebuild the same stack on a staging site before you touch production.
  • Access: You need a VPS with root or sudo rights, and you cannot install this on shared hosting yourself.
  • A backup: Keep a current backup of your configuration files and your site.
  • A rollback plan: Write down the old port settings of your web server.

If you are unsure about backups, start with our website backup strategy guide. You can also confirm where your domain points with our DNS lookup tool.

How do you install Varnish Cache?

On Debian and Ubuntu based systems, Varnish comes from the distribution package repository. However, the packaged version can lag a little behind the current stable release. If you need a newer one, follow the repository instructions on the official Varnish site.

sudo apt update
sudo apt install varnish
varnishd -V

The last command prints the installed version. On RHEL family systems, the package name is still varnish, and you install it with dnf. After installation, the systemd service is ready, but you still have to adjust the default port and memory setting for your own server.

To see the command the package starts, look at the unit file. Its ExecStart line holds the listen address (-a), the VCL file (-f), and the storage (-s). Details differ by distribution, so read the line below as an example only.

sudo systemctl edit --full varnish

# Example ExecStart line (values are examples):
ExecStart=/usr/sbin/varnishd -a :6081 -f /etc/varnish/default.vcl -s malloc,256m

How do you place Varnish in front of Nginx or Apache?

The core idea is simple: Varnish talks to the visitor, and Nginx or Apache becomes the backend. To make that work, you move the web server off its public port and onto a local one. Varnish then takes over the public port. A test port makes the switch safe.

StageVarnishWeb server
Testing6081 (public)80 (as it is today)
Going live80 (public)8080 (local only)

First, run Varnish on a port such as 6081 and test it. Then judge the results. Only when you are happy with the result do you swap the ports. If something breaks, you revert a single setting and return to the old setup. The port numbers in this table are examples, so your stack may use other values.

With Apache, you change the Listen and VirtualHost lines to 8080. With Nginx, you change the listen line in the relevant server block. Then you define the backend address on the Varnish side, which we do in the VCL section.

Does Varnish work with HTTPS, and why do you need TLS termination?

Classic Varnish Cache did not speak TLS, so you had to put a separate component in front of it to decrypt HTTPS traffic. The current Varnish project page and the Varnish Software documentation now also mention built in TLS support. For that reason, check the documentation for your own version.

In practice, the most common setup works like this. Nginx accepts the HTTPS connection on port 443 and passes the request to Varnish, and Varnish then goes to the backend. A dedicated TLS terminator such as Hitch can do the same job. The Varnish Software documentation explains that these two pieces can talk over the PROXY protocol, and you can read the details in its TLS documentation.

If you are new to certificates, our guide on what an SSL certificate is is a good start. After setup, check your certificate with our SSL checker.

How do you set up TLS termination in Nginx and connect it to Varnish?

In short, the example below shows the layout where Nginx accepts HTTPS and forwards to Varnish. The name example.com is a sample domain, and the certificate paths follow the common Let's Encrypt directory layout. Use your own paths.

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:6081;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

The X-Forwarded-Proto header matters. The backend application learns from it that the request actually arrived over HTTPS. Without it, applications such as WordPress can fall into a redirect loop. For the details of proxy_pass and proxy_set_header, see the Nginx proxy module documentation.

What is VCL, and how is a configuration structured?

VCL stands for Varnish Configuration Language. It lets you write a small program that tells Varnish how to treat every request. In short, a file contains a backend block that defines the origin server, plus subroutines that hook into points of the request lifecycle.

  • vcl_recv: Runs when a request arrives. Here you decide whether the request may enter the cache.
  • vcl_backend_response: Runs when the backend answers. Here you set how long to keep the object.
  • vcl_deliver: Runs as the response leaves. It is a good place to add test headers.
  • vcl_hash: Decides what the cache key consists of.

After your code, Varnish also runs its own built in VCL. According to the documentation, this built in code provides sensible defaults for an HTTP cache. You can print a copy with the command varnishd -x builtin, and the built in VCL page explains the idea.

How do you write your first VCL file?

The file below is the smallest working example, so start there. It connects the backend to the web server on port 8080, adds a test header, and lets the built in rules handle everything else. You can save it as /etc/varnish/default.vcl.

vcl 4.1;

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT";
    } else {
        set resp.http.X-Cache = "MISS";
    }
}

Check the syntax before you load it. If there is an error, the command warns you, so your live configuration stays safe. Then you load the new file into the running Varnish and activate it.

varnishd -C -f /etc/varnish/default.vcl
sudo varnishadm vcl.load fresh /etc/varnish/default.vcl
sudo varnishadm vcl.use fresh

Why does Varnish skip the cache when cookies are present?

The Varnish documentation states that the built in vcl_recv code prevents caching when a request carries a cookie. However, the reasoning is sound. A cookie often means personal content, and showing one person's page to another is a serious privacy mistake.

The problem is that most sites hand cookies to anonymous visitors too. Analytics, advertising, and theme cookies all look personal to Varnish. As a result, your hit rate stays far below what you expected, and you never see the gain.

So the fix is to split cookies into two groups. First, you keep the ones that define sessions and carts. You remove purely browser side analytics cookies before the request reaches the cache logic. The documentation also notes that if you trust your backend, you can switch this behavior off by returning early from the vcl_req_cookie subroutine.

The response side has a similar rule: the built in code does not cache responses that carry a Set-Cookie header. So when a plugin creates needless cookies on a page, review the plugin first.

What cache bypass rules should a WordPress site use?

On WordPress, the first group that must never enter the cache is the admin and login area. Next, logged-in users and visitors who left a comment must bypass it. Then come the cart cookies of an e-commerce plugin. The example below shows this logic, and you should confirm your own plugins' cookie names in the browser developer tools.

sub vcl_recv {
    if (req.url ~ "^/(wp-admin|wp-login\.php)") {
        return (pass);
    }
    if (req.http.Cookie ~ "wordpress_logged_in_|comment_author_") {
        return (pass);
    }
    unset req.http.Cookie;
}

The last line removes all remaining cookies. This method is common but risky: if a theme or plugin feature depends on a cookie, you break that feature silently. So test forms, search, and membership flows on a staging site before you go live.

Your platform choice also shapes the caching plan. For that decision, see our guide on WordPress versus a custom website.

How do you protect cart and checkout pages in e-commerce?

In e-commerce, the margin for error is tiny. Showing one customer's cart to someone else destroys both trust and sales. For that reason, cart, checkout, and account pages must bypass the cache in every case. Product lists and category pages, however, can safely enter the cache for anonymous visitors.

sub vcl_recv {
    if (req.url ~ "^/(cart|checkout|my-account)") {
        return (pass);
    }
    if (req.http.Cookie ~ "woocommerce_items_in_cart|wp_woocommerce_session_") {
        return (pass);
    }
}

Also, this example uses common WooCommerce cookie names and English paths. If your store uses different URL paths, adapt them. In a sample store, product pages come from the cache while the cart always comes from the live server.

We explored the sales impact of speed in does e-commerce page speed affect sales. For an end to end plan for your store, see our e-commerce consulting service.

How do you purge the cache?

When you update content, you purge the cache so that visitors do not receive the old version. The Varnish documentation describes two ways. A purge removes one object and its variants from the cache. A ban works like a filter applied to the objects already stored.

Because strangers could otherwise empty your cache, you must limit purge requests with an access control list (ACL). The documentation stresses this point as well. The example below is a short adaptation of the documented logic, and the IP address comes from a documentation range.

acl purge {
    "localhost";
    "203.0.113.10";
}

sub vcl_recv {
    if (req.method == "PURGE") {
        if (!client.ip ~ purge) {
            return (synth(405, "Not allowed."));
        }
        return (purge);
    }
}

From inside the server, one command purges a single URL: curl -X PURGE http://127.0.0.1:6081/sample-page/ . On WordPress, you can pick a plugin that sends this request whenever content changes. For more detail, read the Varnish purging documentation.

How do you check that Varnish works and monitor the hit rate?

After setup, first look at the response headers. Varnish adds headers such as Age and Via. If you also added the X-Cache header above, you see HIT or MISS directly. If the second request does not show HIT, the cache is not working.

curl -sI https://example.com/ | grep -i -E "x-cache|age|via"

For numbers, the varnishstat tool is enough. Because the output is a snapshot, you compare the cache_hit and cache_miss counters to estimate the hit rate. To follow a single request step by step, you use varnishlog.

varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss
varnishlog -g request -q 'ReqURL eq "/"'

When the rate is low, the cause is usually cookies, Cache-Control headers, or tracking parameters appended to URLs. So your first stop should be the cookie and header rules.

Tracking parameters from ad campaigns can also split the cache. For example, a URL with a different parameter on every click is a separate page to Varnish. In that case, you might remove known tracking parameters from the cache key in VCL. Before you do, make sure the application does not use the parameter to change page content.

How does Varnish affect SEO and Core Web Vitals?

Still, Varnish is not a ranking signal by itself. However, it shortens server response time, so time to first byte improves, and that contributes indirectly to loading metrics. Do not promise a real effect before you measure it.

To measure, record the current state first, then switch Varnish on and repeat the same test. Our guide on the Google Lighthouse performance test suits this comparison. For the meaning of the metrics, see what Core Web Vitals are.

A faulty cache setup can also hurt SEO. For example, stale content that lingers for days, redirect loops, or error status codes that enter the cache all affect crawlers too. We check the same points during technical audits in our SEO consulting projects.

Which HTTP headers does Varnish Cache use to decide?

Varnish Cache reads most of its caching decisions from the headers your backend sends. The max-age and s-maxage values inside Cache-Control come first. You can set s-maxage separately for shared caches, and the standard definition of these rules sits in the RFC 9111 text we mentioned earlier.

If the backend names no lifetime, Varnish falls back to its own default time. That value is a parameter and lives in the documentation of your version, so we do not quote a number here. Still, having your application send correct headers is cleaner than forcing a lifetime in VCL.

  • Cache-Control: States how long to keep the response and whether to cache it at all.
  • Vary: Names the request header that changes the response, for example Accept-Encoding.
  • Set-Cookie: Can cause Varnish to skip caching the response.
  • Age: Shows how long the object has stayed in the cache.

Pay special attention to Vary. A badly written Vary header creates dozens of copies of the same page in the cache, so your hit rate falls.

How do you handle static files and images in Varnish Cache?

Images, CSS, and JavaScript files are the best content to cache, because they do not change per person. However, these files often arrive with cookies, and Varnish Cache skips them when it sees a cookie. For that reason, removing cookies on static extensions is a sensible rule.

sub vcl_recv {
    if (req.url ~ "\.(css|js|png|jpg|jpeg|gif|svg|webp|woff2)$") {
        unset req.http.Cookie;
    }
}

On the other hand, if you do not version file names, an updated file can still be served in its old form. Changing the file name when the content changes, or using a version parameter, prevents that problem. Shrinking image size is a separate job, so Varnish does not do it.

Which alternatives exist besides Varnish Cache?

Still, Varnish is not the only option. Depending on your site, budget, and admin skills, simpler paths are often enough. The table below compares common choices, and you should confirm the details in each tool's official documentation.

OptionStrengthWatch out for
Varnish CacheFine control with VCL, strong response cacheNeeds setup and maintenance skills
Nginx FastCGI cacheNo extra service requiredPurging and flexibility can be limited
WordPress cache pluginEasy management from the dashboardSmaller gain at the server level
CDNGeographic distribution, static contentDynamic page rules need separate setup

So the decision should match the complexity you can manage. If nobody on your team can own this work, a simpler solution is safer in the long run.

What common mistakes should you avoid when you set up Varnish?

The mistakes repeat from setup to setup, and most are easy to prevent. Most come from cookie and header handling or from mixed up ports. The list below collects the points to check before you go live.

  • Deleting every cookie: If you remove session and cart cookies too, users can see each other's content.
  • Not forwarding the HTTPS signal: Without X-Forwarded-Proto, the application can fall into a redirect loop.
  • Leaving purge open: Without an ACL, anyone can empty your cache.
  • Setting memory blindly: A value above the server's RAM slows the whole system.
  • Testing only the home page: Also try cart, login, and form pages.

Another frequent mistake is caching error pages for too long, because the damage lingers. For example, if a temporary 503 response enters the cache, visitors can keep seeing the error after you fix the problem. So keep the lifetime of error status codes short, and trigger a deliberate error during testing to watch the behavior.

On the security side, protect the web application itself, not only the cache. Our OWASP Top 10 guide gives you a solid checklist. A cache is not a firewall.

What checklist should you follow before you go live?

Do not treat a Varnish Cache setup as a one time job. If you follow the steps in order, you lower your risk. The sequence below helps when you move a stack you tested on staging to production.

  1. Compile the VCL file with varnishd -C on staging and confirm that it has no errors.
  2. Test login, cart, checkout, and form flows with two browsers, one anonymous and one logged in.
  3. Confirm that the second request shows HIT through the X-Cache header.
  4. Confirm that a purge request works only from the allowed IP address.
  5. Keep the old port settings ready for a rollback.
  6. Watch the hit rate and the error logs regularly during the first days.

When you finish this list, you have a solid base. Moreover, because you planned backups, monitoring, and rollback from the start, you stay calm if something goes wrong. Everyone on your team can also read the comments in the file and see why each rule exists, so maintenance gets easier.

When should you not install Varnish Cache yourself and leave it to your hosting provider?

So let us be honest: Varnish is not the right tool for every site or every team. On shared hosting, you have no root access, so you cannot install it anyway. In that case, using the cache layer your provider offers is healthier.

  • If you lack root access and command line experience, leave the setup to your provider or a system administrator.
  • Do not run your first experiment on a live store, and build a staging copy first.
  • If your host already offers a cache, ask their support before you add a second layer.
  • If your real problem is a slow database query or heavy images, fix that first.

Provider choice plays a role in this decision too. Our guide on how to choose web hosting helps you see which plan gives which flexibility. Our team does not run hosting, so we offer only a framework based on official documentation here.

If you want to plan the technical base and the performance of your website together, our web design service covers it.

Frequently Asked Questions

Is Varnish Cache free?
Yes, Varnish Cache is open source software, and you can use the community edition for free. Varnish Software also sells a paid enterprise edition. You should verify which feature belongs to which edition in the official documentation of the package you install. Also remember that you need server resources and some admin time to run it well.
Does Varnish work on shared hosting?
Usually no, because you must install Varnish at the server level, change ports, and start it as a service. These steps need root rights. On shared hosting you do not have that access, so you cannot set it up yourself. A host side page cache, a cache plugin, or a CDN fits better there.
Can you use Varnish and Redis together?
Yes, you can run both on the same site, because they work at different layers. Varnish stores the finished HTTP response, while Redis holds the data cache of your application. On pages that Varnish bypasses, such as the cart and login area, Redis keeps reducing the load. Neither replaces the other.
Does Varnish support HTTPS?
In the classic setup, you place a TLS terminator such as Nginx or Hitch in front of Varnish. The current Varnish project page and the Varnish Software documentation also mention built in TLS support, although it can depend on your version. Check the official documentation for your release. The terminator setup remains the most common and best documented path.
How do you clear the Varnish cache?
Varnish offers two methods: purge and ban. A purge removes one object and its variants from the cache, and a ban applies a filter to the objects already stored. You should define an ACL so that only trusted IP addresses can send these requests. On WordPress, plugins can purge automatically when you update content.
Is Varnish safe on a WooCommerce store?
With correct rules it is safe, and with wrong rules it is risky. You must bypass cart, checkout, and account pages, and you must keep requests that carry session or cart cookies out of the cache. Before you go live, test the full cart, login, and checkout flow on a staging site from start to finish.
  • varnish cache
  • http cache
  • reverse proxy
  • vcl
  • nginx
  • wordpress caching
  • site speed
Share:
Talha Aslan

Google Partner digital marketing expert. Hands-on with SEO, Google Ads, web design and e-commerce projects since 2012; every post here comes from that experience.

Next project

Let's talk about your project.

Your brief goes straight to Talha Aslan and team: strategy led by Talha, delivery by an experienced team. The first consultation is free; we listen and come back with a clear roadmap.