Custom Varnish VCL Rules: Boost Site Speed & Reduce Server Load

Custom Varnish VCL Rules: Boost Hit Rate & Reduce Load

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1286
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1243
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    983
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1034
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1107
  • image_website-_0.webp
    Website development for Red Pear
    555

Custom Varnish VCL Rules: Boost Hit Rate & Reduce Load

Default Varnish configuration often works inefficiently: it caches everything or fails to cache critical pages, ignores authorization headers, and breaks on edge cases with cookies. The result is a low hit rate (30–40%) and excessive backend load. If you're facing this issue, request an audit of your current Varnish configuration. With over 7 years of experience and 50+ projects focused on optimization, we guarantee an increase in hit rate to 90%+ while preserving full business logic. One of our clients—an e-commerce store with 500,000 requests per hour—saw their hit rate jump from 35% to 93% in just 2 days after implementing custom rules. This reduced backend load by 8x and saved up to 70% on server costs.

Varnish Cache uses VCL to describe caching policies.

How Custom VCL Rules Accelerate Your Site?

Custom VCL rules address specific needs: conditional cache control, request normalization, bypassing CDN for certain routes, routing to different backends, and grace mode when the origin is down. Let's dive into key aspects.

Request normalization

Without normalization, the same resource is stored under dozens of keys: /?utm_source=google, /?utm_source=facebook—these are separate cache entries even though the content is identical. Statistics show that URLs with utm tags waste up to 30% of cache space. Normalization solves this.

vcl 4.1; import std; import directors; backend default { .host = "127.0.0.1"; .port = "8080"; .connect_timeout = 2s; .first_byte_timeout = 60s; .between_bytes_timeout = 10s; .probe = { .url = "/healthz"; .timeout = 1s; .interval = 5s; .window = 5; .threshold = 3; } } backend api { .host = "127.0.0.1"; .port = "8081"; .connect_timeout = 1s; .first_byte_timeout = 30s; } sub vcl_recv { # Remove marketing parameters if (req.url ~ "(\\?|&)(utm_source|utm_medium|utm_campaign|utm_term|utm_content|fbclid|gclid|yclid|_ga|mc_eid)=") { set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_term|utm_content|fbclid|gclid|yclid|_ga|mc_eid)=[^&]*", ""); set req.url = regsuball(req.url, "\\?(utm_source|utm_medium|utm_campaign|utm_term|utm_content|fbclid|gclid|yclid|_ga|mc_eid)=[^&]*&", "?"); set req.url = regsub(req.url, "\\?$", ""); } # Normalize Accept-Encoding if (req.http.Accept-Encoding) { if (req.url ~ "\\.(jpg|jpeg|png|gif|webp|gz|tgz|bz2|tbz|mp3|ogg|swf|flv|mp4|woff2?)$") { unset req.http.Accept-Encoding; } else if (req.http.Accept-Encoding ~ "br") { set req.http.Accept-Encoding = "br"; } else if (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } else { unset req.http.Accept-Encoding; } } # Normalize cookies if (req.http.Cookie) { set req.http.Cookie = ";" + req.http.Cookie; set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); set req.http.Cookie = regsuball(req.http.Cookie, ";(session|auth_token|XSRF-TOKEN)=", "; \\1="); set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); if (req.http.Cookie == "") { unset req.http.Cookie; } } # Device detection for adaptive caching if (req.http.User-Agent ~ "(?i)mobile|android|iphone|ipod|blackberry|opera mini|iemobile") { set req.http.X-Device-Type = "mobile"; } else { set req.http.X-Device-Type = "desktop"; } # Route by content type if (req.url ~ "^/api/") { return(pass); } if (req.http.Authorization || req.http.Cookie ~ "auth_token=") { return(pass); } if (req.method != "GET" && req.method != "HEAD") { return(pass); } if (req.url ~ "\\.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot|webp|avif)(\\?.*)?$") { unset req.http.Cookie; return(hash); } return(hash); } sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } hash_data(req.http.X-Device-Type); return(lookup); } 

What is grace mode and how does it work?

Grace mode allows serving stale cache while the backend is overloaded or temporarily unavailable. This is critical for high-traffic sites.

sub vcl_backend_response { set beresp.grace = 24h; if (beresp.status >= 500) { set beresp.ttl = 0s; set beresp.grace = 60s; return(deliver); } # Custom TTL by content type if (bereq.url ~ "^/news/") { set beresp.ttl = 10m; } else if (bereq.url ~ "^/static/") { set beresp.ttl = 30d; unset beresp.http.Set-Cookie; } else if (bereq.url ~ "^/product/") { set beresp.ttl = 1h; } else { set beresp.ttl = 5m; } if (beresp.http.Cache-Control ~ "no-store|private") { set beresp.uncacheable = true; return(deliver); } } sub vcl_hit { if (obj.ttl >= 0s) { return(deliver); } if (obj.ttl + obj.grace > 0s) { return(deliver); } return(restart); } 

How to implement cache invalidation via VCL?

Tag-based purge (via xkey) is the right approach for CMS with object dependencies.

import xkey; acl purge_acl { "127.0.0.1"; } sub vcl_recv { if (req.method == "PURGE") { if (!client.ip ~ purge_acl) { return(synth(405, "Not allowed")); } return(purge); } if (req.method == "XKEY-PURGE") { if (!client.ip ~ purge_acl) { return(synth(405, "Not allowed")); } set req.http.n-gone = xkey.softpurge(req.http.xkey-purge); return(synth(200, "Purged " + req.http.n-gone + " objects")); } } sub vcl_backend_response { if (beresp.http.Surrogate-Key) { set beresp.http.xkey = beresp.http.Surrogate-Key; } } 

Comparison of invalidation methods:

Method Speed Granularity Best for
PURGE by URL Instant High (single URL) Individual updates
PURGE by tags (xkey) Instant Medium (all objects with tag) Bulk updates (categories)
Full cache flush Requires warm-up Low (entire cache) Rare global changes

Debugging and monitoring

sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; set resp.http.X-Cache-Hits = obj.hits; } else { set resp.http.X-Cache = "MISS"; } set resp.http.X-Served-By = server.hostname; unset resp.http.X-Powered-By; unset resp.http.Server; unset resp.http.X-Varnish; unset resp.http.Via; } 
Commands for debugging VCL

Monitoring via varnishstat and varnishlog:

# Current hit rate varnishstat -f MAIN.cache_hit,MAIN.cache_miss # Live log filtered by URL varnishlog -q 'ReqURL ~ "^/news/"' -g request # Top cache miss by URL varnishtop -i ReqURL -q 'VCL_call eq "MISS"' 

Why request normalization is critical for hit rate?

Request normalization is the foundation of efficient caching. Without it, hit rate can be below 50% even with properly configured TTL. For example, URLs with utm tags waste up to 30% of cache space. Normalization also prevents issues with cookie-dependent content and incorrect caching of dynamic pages. Custom VCL rules boost hit rate by 2–3x compared to default configuration, as confirmed by our projects.

How to set up request normalization?

  1. Identify parameters to remove (utm, fbclid, gclid, etc.).
  2. Write vcl_recv that strips these parameters from req.url.
  3. Normalize Accept-Encoding—prioritize br, then gzip.
  4. Process cookies: remove all but session-essential ones.
  5. Add device-aware hashing for mobile/desktop separation.
  6. Test with varnishtest and monitoring.

Implementation process

A typical custom VCL rules project includes the following stages:

  • Analysis (1–2 days): audit current traffic, analyze backend response headers, identify non-cacheable patterns (cookies, Cache-Control: private).
  • Design (1 day): develop VCL rule architecture, define cache keys, grace periods, and routing.
  • Implementation (2–3 days): write VCL scripts, configure health checks, integrate with CDN.
  • Testing (1 day): validate on staging with varnishtest, measure hit rate, compare with baseline.
  • Deployment (1 day): roll out to production, set up monitoring, document.

Complex cases (A/B testing via Varnish, ESI includes, multi-level caching with Nginx) add 3–5 days.

Scope of work

  • Custom VCL rules tailored to project architecture.
  • URL, cookie, and Accept-Encoding normalization.
  • Grace mode and stale-while-revalidate.
  • Cache invalidation via PURGE/xkey.
  • Integration with CDN and deployment systems.
  • Load testing and monitoring setup (varnishstat, metrics).
  • Documentation of implemented rules and invalidation procedures.

Comparison: default config vs custom VCL

Parameter Default configuration Custom VCL rules
Hit rate 30–40% 85–95%
URL normalization No Full (utm, fbclid, excess cookies)
Grace mode None Configurable (24h+)
Invalidation Only full flush PURGE by URL and tags
Device-aware caching No Yes (separate objects for mobile/desktop)
Backend load High Reduced 5–10x

Request an audit of your current Varnish configuration—we'll identify bottlenecks and propose custom solutions. Contact us for a tailored offer.