BY THIJS FERYN
Slow websites
SUCK
WEB PERFORMANCE IS AN
ESSENTIAL PART OF THE
USER EXPERIENCE
SLOW~DOWN
THROWING
SERVERS
ATTHEPROBLEM
MO' MONEY
MO' SERVERS
MO' PROBLEMS
IDENTIFY SLOWEST PARTS
OPTIMIZE
AFTER A WHILE YOU HIT THE LIMITS
CACHING
CACHE
INVALIDATION
CACHE PURGING
WHY
RECOMPUTE
IF THE DATA
HASN'T
CHANGED?
HI, I'M THIJS
I'M THE TECH EVANGELIST
AT VARNISH SOFTWARE
WE BUILD SOFTWARE-DEFINED
WEB ACCELERATION & CONTENT
DELIVERY SOLUTIONS
SERVER
USER
UNDER PRESSURE
SERVER
USER VARNISH SERVER
HTTP HAS BUILT-IN
CACHING MECHANISMS
Cache-Control: public, max-age=500
Cache-Control: private, no-cache, no-store
AND VARNISH
COMPLIES TO THOSE
HTTP CACHING
CONVENTIONS
VARNISH CONFIGURATION LANGUAGE
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
if(req.url ~ "^/admin(/.*|$)") {
return(pass);
}
unset req.http.Cookie;
}
vcl 4.1;
import cookie;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
if (req.http.cookie) {
cookie.parse(req.http.cookie);
cookie.keep("PHPSESSID");
set req.http.cookie = cookie.get_string();
if (req.http.cookie ~ "^s*$") {
unset req.http.cookie;
}
}
}
PUTTING STUFF IN
THE BOXES: ADDING
PAGES & OTHER
OBJECTS TO THE
CACHE
EMPTYING
THE BOXES
THERE'S ONLY ONE THING WORSE
THAN NOT CACHING ENOUGH, AND
THAT'S CACHING FOR TOO LONG
"
THIJS FERYN
WHEN ARE OBJECTS REMOVED?
1. EXPIRATION WHEN THE REMAINING TTL HITS ZERO
2. LRU NUKING WHEN THE CACHE IS FULL
3. PURGE REMOVE ONE OBJECT
4. BAN REMOVE MULTIPLE OBJECTS USING PATTERN MATCHING
5. SECONDARY KEYS REMOVE MULTIPLE OBJECTS USING TAGS
1. EXPIRATION
Cache-Control: public, max-age=500
sub vcl_backend_response {
set beresp.ttl = 500s;
}
$ varnishadm param.show default_ttl
default_ttl
Value is: 120.000 [seconds] (default)
Minimum is: 0.000
The TTL assigned to objects if neither the backend nor the VCL
code assigns one.
NB: This parameter is evaluated only when objects are created.
To change it for all objects, restart or ban everything.
varnishstat -f MAIN.n_object -f MAIN.n_expired
MAIN.n_object 10 object structs made
MAIN.n_expired 5 Number of expired objects
2. LRU NUKING
varnishstat -1 -f MAIN.n_object -f MAIN.n_expired 
-f MAIN.n_lru_nuked -f "SMA.*.g_bytes" -f "SMA.*.g_space"
MAIN.n_object 938751 object structs made
MAIN.n_expired 100 Number of expired objects
MAIN.n_lru_nuked 20 Number of LRU nuked objects
SMA.s0.g_bytes 104857600 Bytes outstanding
SMA.s0.g_space 1048576 Bytes available
SMA.Transient.g_bytes 0 Bytes outstanding
SMA.Transient.g_space 0 Bytes available
3. PURGING
acl purge {
"localhost";
"127.0.0.1";
"::1";
"172.16.0.0/12";
}
sub vcl_recv {
if(req.method == "PURGE") {
if(!client.ip ~ purge) {
return(synth(405));
}
return (purge);
}
}
curl -XPURGE http://localhost
PURGE / HTTP/1.1
Host: localhost
HTTP/1.1 200 Purged
Server: Varnish
X-Varnish: 2
Content-Type: text/html; charset=utf-8
Content-Length: 236
<!DOCTYPE html>
<html>
<head>
<title>200 Purged</title>
</head>
<body>
<h1>Error 200 Purged</h1>
<p>Purged</p>
<h3>Guru Meditation:</h3>
<p>XID: 2</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
$ varnishstat -1 -f MAIN.n_purges
MAIN.n_purges 1 . Number of purge operations executed
bin/magento setup:config:set --http-cache-hosts=localhost
varnishlog -g request -q "ReqMethod eq 'PURGE'"
* << Request >> 131079
- Begin req 131078 rxreq
- Timestamp Start: 1733554258.896232 0.000000 0.000000
- Timestamp Req: 1733554258.896232 0.000000 0.000000
- ReqStart 172.19.0.1 58068 a0
- ReqMethod PURGE
- ReqURL /
- ReqProtocol HTTP/1.1
- ReqHeader Host: localhost
- ReqHeader User-Agent: curl/8.7.1
- ReqHeader Accept: */*
- ReqHeader X-Forwarded-For: 172.19.0.1
- VCL_call RECV
- ReqHeader Surrogate-Capability: Varnish=ESI/1.0
- ReqURL /
- ReqURL /
- ReqHeader X-Forwarded-Proto: http
- VCL_acl MATCH purge "172.16.0.0/12"
- VCL_return purge
- VCL_call HASH
- VCL_return lookup
- VCL_call PURGE
- VCL_return synth
- RespHeader Date: Sat, 07 Dec 2024 06:50:58 GMT
- RespHeader Server: Varnish
- RespHeader X-Varnish: 131079
- RespProtocol HTTP/1.1
- RespStatus 200
- RespReason OK
- RespReason Purged
- VCL_call SYNTH
- RespHeader Content-Type: text/html; charset=utf-8
- RespHeader Retry-After: 5
- VCL_return deliver
- Timestamp Process: 1733554258.896488 0.000256 0.000256
- RespHeader Content-Length: 241
- Storage mse s0
- RespHeader Accept-Ranges: bytes
- RespHeader Connection: keep-alive
- Timestamp Resp: 1733554258.897431 0.001198 0.000942
- ReqAcct 74 0 74 219 241 460
4. BANNING
<field> <operator> <arg> [&& <field> <oper> <arg> ...]
BAN
EXPRESSIONS
MATCH
MULTIPLE OBJECTS
req.url == / && req.http.host == example.com
obj.status == 404
obj.http.Content-Type ~ ^image/
req.url ~ ^/products(/.+|$) && req.http.host == example.com
$ varnishadm ban "obj.http.Content-Type ~ ^image/"
acl purge {
"localhost";
"127.0.0.1";
"::1";
"172.16.0.0/12";
}
sub vcl_recv {
if (req.method == "PURGE") {
if (!client.ip ~ purge) {
return (synth(405));
}
if (!req.http.x-invalidate-pattern) {
return (purge);
}
ban("req.url ~ ^" + req.http.x-invalidate-pattern
+ " && req.http.host == " + req.http.host);
return (synth(200,"Ban added"));
}
}
curl -XPURGE -H "x-invalidate-pattern:/products/" 
http://localhost
$ varnishadm ban.list
Present bans:
1603272627.622051 0 - obj.http.Content-Type eq text/css
1603270370.244746 11 C
$ varnishadm ban.list
Present bans:
1603272627.622051 11 - obj.http.Content-Type eq text/css
$ varnishadm ban.list
Present bans:
1603272627.622051 11 C obj.http.Content-Type eq text/css
$ varnishstat -1 -f MAIN.bans
MAIN.bans 1 . Count of bans
Purge-Cache-Tags: config:block_list
config:block.block.olivero_account_menu
config:block.block.olivero_search_form_wide
config:block.block.olivero_breadcrumbs
config:block.block.olivero_content config:block.block.olivero_help
config:block.block.olivero_page_title
config:block.block.olivero_main_menu
config:block.block.olivero_search_form_narrow
config:block.block.olivero_messages
config:block.block.olivero_primary_admin_actions
config:block.block.olivero_primary_local_tasks
config:block.block.olivero_secondary_local_tasks
config:block.block.olivero_powered
config:block.block.olivero_site_branding
config:block.block.olivero_syndicate block_view node_view node:1
config:filter.format.basic_html user:1 local_task
config:system.menu.account config:search.settings
CACHE_MISS_IF_UNCACHEABLE_HTTP_METHOD:form config:system.menu.main
config:system.site rendered http_response config:user.role.anonymous
$ varnishadm ban.list
Present bans:
1727438962.423744 2 - obj.http.X-Magento-Tags ~ ((^|,)cat_p_1(,|$))
1727438962.414895 0 C obj.http.X-Magento-Tags ~ .*
1727273313.798067 1681 C
X-Magento-Tags:
store,cms_b,cms_b_1,cms_b_footer_links_block,cat_p_1,cat_p,cat_p_6,cat_p
_3,cat_p_4,cat_p_5,cat_p_7,cat_p_12,cat_p_14,cat_p_13,review_block
PURGE / HTTP/1.1
Host: localhost
X-Magento-Tags-Pattern: ((^|,)cat_p_1(,|$))
PURGE / HTTP/1.1
Host: localhost
X-Magento-Tags-Pattern: .*
$ varnishadm ban.list
Present bans:
1727438962.423744 2 - obj.http.X-Magento-Tags ~ ((^|,)cat_p_1(,|$))
1727438962.414895 0 C obj.http.X-Magento-Tags ~ .*
1727273313.798067 1681 C
THE BAN LURKER
THREAD PROCESSES
THE BAN LIST
obj.http.Content-Type ~ ^image/
req.url ~ ^/products(/.+|$) && req.http.host == example.com
NOT
LURKER
FRIENDLY
LURKER
FRIENDLY
sub vcl_backend_response {
set beresp.http.url = bereq.url;
set beresp.http.host = bereq.http.host;
}
sub vcl_deliver {
unset resp.http.url;
unset resp.http.host;
}
INJECT
REQUEST
INFORMATION
acl purge {
"localhost";
"127.0.0.1";
"::1";
"172.16.0.0/12";
}
sub vcl_recv {
if (req.method == "PURGE") {
if (!client.ip ~ purge) {
return (synth(405));
}
if (!req.http.x-invalidate-pattern) {
return (purge);
}
ban("obj.http.url ~ " + req.http.x-invalidate-pattern
+ " && obj.http.host == " + req.http.host);
return (synth(200,"Ban added"));
}
}
ban("obj.http.url ~ " + req.http.x-invalidate-pattern
+ " && obj.http.host == " + req.http.host);
varnishadm ban obj.http.url ~ /products && obj.http.host ==
example.com
varnishlog -g request -q "ReqMethod eq 'PURGE'"
* << Request >> 65538
- Begin req 65537 rxreq
- Timestamp Start: 1733555192.617397 0.000000 0.000000
- Timestamp Req: 1733555192.617397 0.000000 0.000000
- VCL_use boot
- ReqStart 172.19.0.3 60574 http
- ReqMethod PURGE
- ReqURL /
- ReqProtocol HTTP/1.1
- ReqHeader Host: varnish
- ReqHeader user-agent: purge_purger_http module for Drupal 8.
- ReqHeader purge-cache-tags: node_list,node_list:page,node:1
- ReqHeader X-Forwarded-For: 172.19.0.3
- ReqHeader Via: 1.1 fddab3bb8c94 (Varnish/7.6)
- VCL_call RECV
- ReqHeader Surrogate-Capability: Varnish=ESI/1.0
- ReqUnset Host: varnish
- ReqHeader Host: varnish
- ReqURL /
- ReqHeader X-Forwarded-Proto: http
- VCL_return synth
- VCL_call HASH
- VCL_return lookup
- RespProtocol HTTP/1.1
- RespStatus 200
- RespReason Ban added.
- RespHeader Date: Sat, 07 Dec 2024 07:06:32 GMT
- RespHeader Server: Varnish
- RespHeader X-Varnish: 65538
- VCL_call SYNTH
- RespHeader Content-Type: text/html; charset=utf-8
- RespHeader Retry-After: 5
- VCL_return deliver
- Timestamp Process: 1733555192.620607 0.003209 0.003209
- RespHeader Content-Length: 252
- Storage malloc Transient
- Filters
- RespHeader Connection: keep-alive
- Timestamp Resp: 1733555192.620675 0.003278 0.000068
- ReqAcct 136 0 136 200 252 452
- End
Σ BANS X Σ OBJECTS = ⏳
5. SECONDARY KEYS
X-Magento-Tags:
store,cms_b,cms_b_1,cms_b_footer_links_block,cat_p_1,cat_p,cat_p_6,cat_p
_3,cat_p_4,cat_p_5,cat_p_7,cat_p_12,cat_p_14,cat_p_13,review_block
MAGENTO
USES TAGS
(AB)USES BANS
DUE TO LACK OF TAG SUPPORT
IN VARNISH
$ varnishadm ban.list
Present bans:
1727438962.423744 2 - obj.http.X-Magento-Tags ~ ((^|,)cat_p_1(,|$))
import ykey;
sub vcl_backend_response {
ykey.add_header(beresp.http.Purge-Cache-Tags, sep=" ");
unset beresp.http.Purge-Cache-Tags;
ykey.add_key("everything");
if(beresp.http.Content-Type ~ "^image/") {
ykey.add_key("image");
}
}
-- BerespHeader Purge-Cache-Tags: config:block_list config:block.block.olivero_account_menu
config:block.block.olivero_search_form_wide config:block.block.olivero_breadcrumbs
config:block.block.olivero_content config:block.block.olivero_help config:block.block.olivero_page_title
config:block.block.olivero_main_menu config:block.block.olivero_search_form_narrow
config:block.block.olivero_messages config:block.block.olivero_primary_admin_actions
config:block.block.olivero_primary_local_tasks config:block.block.olivero_secondary_local_tasks
config:block.block.olivero_powered config:block.block.olivero_site_branding
config:block.block.olivero_syndicate block_view node_view node:1 config:filter.format.basic_html user:1
local_task config:system.menu.account config:search.settings CACHE_MISS_IF_UNCACHEABLE_HTTP_METHOD:form
config:system.menu.main config:system.site rendered http_response config:user.role.anonymous
-- YKEY key: ADD config:block_list
-- YKEY key: ADD config:block.block.olivero_account_menu
-- YKEY key: ADD config:block.block.olivero_search_form_wide
-- YKEY key: ADD config:block.block.olivero_breadcrumbs
-- YKEY key: ADD config:block.block.olivero_content
-- YKEY key: ADD config:block.block.olivero_help
-- YKEY key: ADD config:block.block.olivero_page_title
-- YKEY key: ADD config:block.block.olivero_main_menu
-- YKEY key: ADD config:block.block.olivero_search_form_narrow
-- YKEY key: ADD config:block.block.olivero_messages
-- YKEY key: ADD config:block.block.olivero_primary_admin_actions
-- YKEY key: ADD config:block.block.olivero_primary_local_tasks
-- YKEY key: ADD config:block.block.olivero_secondary_local_tasks
-- YKEY key: ADD config:block.block.olivero_powered
-- YKEY key: ADD config:block.block.olivero_site_branding
-- YKEY key: ADD config:block.block.olivero_syndicate
-- YKEY key: ADD block_view
-- YKEY key: ADD node_view
-- YKEY key: ADD node:1
-- YKEY key: ADD config:filter.format.basic_html
-- YKEY key: ADD user:1
-- YKEY key: ADD local_task
-- YKEY key: ADD config:system.menu.account
-- YKEY key: ADD config:search.settings
-- YKEY key: ADD CACHE_MISS_IF_UNCACHEABLE_HTTP_METHOD:form
-- YKEY key: ADD config:system.menu.main
-- YKEY key: ADD config:system.site
-- YKEY key: ADD rendered
-- YKEY key: ADD http_response
-- YKEY key: ADD config:user.role.anonymous
-- BerespUnset Purge-Cache-Tags
-- YKEY key: ADD everything
import ykey;
acl purge {
"localhost";
"127.0.0.1";
"::1";
}
sub vcl_recv {
if(req.method == "PURGE") {
if(!client.ip ~ purge) {
return(synth(405));
}
if (req.http.Purge-Cache-Tags) {
return (synth(200, ykey.purge_header(req.http.Purge-Cache-Tags,
sep=",") + " objects purged"));
}
return(purge);
}
}
ykey.purge_header(req.http.Purge-Cache-Tags, sep=",")
* << Request >> 65538
- Begin req 65537 rxreq
- Timestamp Start: 1733556901.729447 0.000000 0.000000
- Timestamp Req: 1733556901.729447 0.000000 0.000000
- ReqStart 172.19.0.3 35294 a0
- ReqMethod PURGE
- ReqURL /
- ReqProtocol HTTP/1.1
- ReqHeader Host: varnish
- ReqHeader user-agent: purge_purger_http module for Drupal 8.
- ReqHeader purge-cache-tags: node_list,node_list:page,node:1
- ReqHeader X-Forwarded-For: 172.19.0.3
- VCL_call RECV
- ReqHeader Surrogate-Capability: Varnish=ESI/1.0
- ReqURL /
- ReqURL /
- ReqHeader X-Forwarded-Proto: http
- VCL_acl MATCH purge "172.16.0.0/12"
- YKEY key: PURGE node_list
- YKEY key: PURGE node_list:page
- YKEY key: PURGE node:1
- VCL_return synth
- VCL_call HASH
- VCL_return lookup
- RespHeader Date: Sat, 07 Dec 2024 07:35:01 GMT
- RespHeader Server: Varnish
- RespHeader X-Varnish: 65538
- RespProtocol HTTP/1.1
- RespStatus 200
- RespReason OK
- RespReason 1 objects purged
- VCL_call SYNTH
- RespHeader Content-Type: text/html; charset=utf-8
- RespHeader Retry-After: 5
- VCL_return deliver
- Timestamp Process: 1733556901.733476 0.004029 0.004029
- RespHeader Content-Length: 270
- Storage mse s0
- RespHeader Accept-Ranges: bytes
- RespHeader Connection: keep-alive
- Timestamp Resp: 1733556901.733543 0.004096 0.000067
- ReqAcct 136 0 136 228 270 498
- End
PERFORMANCE
IMPACT OF CACHE
PURGING
CACHE INVALIDATION
MAKE
CACHED OBJECTS
INVALID
NO NEED TO
REMOVE THEM
ykey.purge_header(req.http.Purge-Cache-Tags, sep=",",)
ykey.purge_header(req.http.Purge-Cache-Tags, sep=",",
soft=true)
ASYNCHRONOUS
REVALIDATION
USER VARNISH SERVER
ASYNC FETCH
SEND STALE
RESPONSE WHILE
FETCHING
OBJECT LIFETIME = TTL + GRACE + KEEP
OBJECT LIFETIME = TTL + GRACE + KEEP
DEFAULT VALUE:
2 MINUTES
OBJECT LIFETIME = TTL + GRACE + KEEP
SERVE STALE
CONTENT, ASYNC
REVALIDATION
DEFAULT VALUE: 10
SECONDS
CAN BE SET BY
"STALE-WHILE-
REVALIDATE"
OBJECT LIFETIME = TTL + GRACE + KEEP
KEEP THE OBJECT
AROUND FOR LATER
USE
DEFAULT VALUE:
0 SECONDS
SYNCHRONOUS
REVALIDATION
OBJECT LIFETIME = TTL + GRACE + KEEP
SOFT PURGING
SETS TTL TO ZERO
sub vcl_backend_response {
set beresp.grace = 1d;
}
import ykey;
sub vcl_backend_response {
ykey.add_header(beresp.http.Purge-Cache-Tags, sep=" ");
unset beresp.http.Purge-Cache-Tags;
ykey.add_key("everything");
if(beresp.http.Content-Type ~ "^image/") {
ykey.add_key("image");
}
set beresp.grace = 1d;
}
Cache-Control: max-age=60, public, stale-while-revalidate=86400
- VCL_call HASH
- VCL_return lookup
- Hit 32775 -25.943176 7200.000000 0.000000
- VCL_call HIT
- VCL_return deliver
- Link bereq 34 bgfetch
$ varnishstat -1 -f MAIN.cache_hit_grace
MAIN.cache_hit_grace 1 Cache grace hits
1. EXPIRATION
WE'RE BACK
AT EXPIRATION
FIND THE RIGHT
FRAMEWORK PLUGIN
OR INTEGRATE
PURGING YOURSELF
The Subtle Art Of Cache Invalidation (FOSSingapore 2024)

The Subtle Art Of Cache Invalidation (FOSSingapore 2024)

  • 1.
  • 2.
  • 3.
    WEB PERFORMANCE ISAN ESSENTIAL PART OF THE USER EXPERIENCE
  • 4.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
    AFTER A WHILEYOU HIT THE LIMITS
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
    I'M THE TECHEVANGELIST AT VARNISH SOFTWARE
  • 22.
    WE BUILD SOFTWARE-DEFINED WEBACCELERATION & CONTENT DELIVERY SOLUTIONS
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
    AND VARNISH COMPLIES TOTHOSE HTTP CACHING CONVENTIONS
  • 31.
  • 33.
    vcl 4.1; backend default{ .host = "127.0.0.1"; .port = "8080"; } sub vcl_recv { if(req.url ~ "^/admin(/.*|$)") { return(pass); } unset req.http.Cookie; }
  • 34.
    vcl 4.1; import cookie; backenddefault { .host = "127.0.0.1"; .port = "8080"; } sub vcl_recv { if (req.http.cookie) { cookie.parse(req.http.cookie); cookie.keep("PHPSESSID"); set req.http.cookie = cookie.get_string(); if (req.http.cookie ~ "^s*$") { unset req.http.cookie; } } }
  • 35.
    PUTTING STUFF IN THEBOXES: ADDING PAGES & OTHER OBJECTS TO THE CACHE
  • 36.
  • 37.
    THERE'S ONLY ONETHING WORSE THAN NOT CACHING ENOUGH, AND THAT'S CACHING FOR TOO LONG " THIJS FERYN
  • 39.
    WHEN ARE OBJECTSREMOVED? 1. EXPIRATION WHEN THE REMAINING TTL HITS ZERO 2. LRU NUKING WHEN THE CACHE IS FULL 3. PURGE REMOVE ONE OBJECT 4. BAN REMOVE MULTIPLE OBJECTS USING PATTERN MATCHING 5. SECONDARY KEYS REMOVE MULTIPLE OBJECTS USING TAGS
  • 40.
  • 41.
  • 42.
    sub vcl_backend_response { setberesp.ttl = 500s; }
  • 43.
    $ varnishadm param.showdefault_ttl default_ttl Value is: 120.000 [seconds] (default) Minimum is: 0.000 The TTL assigned to objects if neither the backend nor the VCL code assigns one. NB: This parameter is evaluated only when objects are created. To change it for all objects, restart or ban everything.
  • 44.
    varnishstat -f MAIN.n_object-f MAIN.n_expired MAIN.n_object 10 object structs made MAIN.n_expired 5 Number of expired objects
  • 45.
  • 46.
    varnishstat -1 -fMAIN.n_object -f MAIN.n_expired -f MAIN.n_lru_nuked -f "SMA.*.g_bytes" -f "SMA.*.g_space" MAIN.n_object 938751 object structs made MAIN.n_expired 100 Number of expired objects MAIN.n_lru_nuked 20 Number of LRU nuked objects SMA.s0.g_bytes 104857600 Bytes outstanding SMA.s0.g_space 1048576 Bytes available SMA.Transient.g_bytes 0 Bytes outstanding SMA.Transient.g_space 0 Bytes available
  • 47.
  • 48.
    acl purge { "localhost"; "127.0.0.1"; "::1"; "172.16.0.0/12"; } subvcl_recv { if(req.method == "PURGE") { if(!client.ip ~ purge) { return(synth(405)); } return (purge); } }
  • 49.
  • 50.
    PURGE / HTTP/1.1 Host:localhost HTTP/1.1 200 Purged Server: Varnish X-Varnish: 2 Content-Type: text/html; charset=utf-8 Content-Length: 236 <!DOCTYPE html> <html> <head> <title>200 Purged</title> </head> <body> <h1>Error 200 Purged</h1> <p>Purged</p> <h3>Guru Meditation:</h3> <p>XID: 2</p> <hr> <p>Varnish cache server</p> </body> </html>
  • 51.
    $ varnishstat -1-f MAIN.n_purges MAIN.n_purges 1 . Number of purge operations executed
  • 54.
  • 55.
    varnishlog -g request-q "ReqMethod eq 'PURGE'"
  • 56.
    * << Request>> 131079 - Begin req 131078 rxreq - Timestamp Start: 1733554258.896232 0.000000 0.000000 - Timestamp Req: 1733554258.896232 0.000000 0.000000 - ReqStart 172.19.0.1 58068 a0 - ReqMethod PURGE - ReqURL / - ReqProtocol HTTP/1.1 - ReqHeader Host: localhost - ReqHeader User-Agent: curl/8.7.1 - ReqHeader Accept: */* - ReqHeader X-Forwarded-For: 172.19.0.1 - VCL_call RECV - ReqHeader Surrogate-Capability: Varnish=ESI/1.0 - ReqURL / - ReqURL / - ReqHeader X-Forwarded-Proto: http - VCL_acl MATCH purge "172.16.0.0/12" - VCL_return purge - VCL_call HASH - VCL_return lookup - VCL_call PURGE - VCL_return synth
  • 57.
    - RespHeader Date:Sat, 07 Dec 2024 06:50:58 GMT - RespHeader Server: Varnish - RespHeader X-Varnish: 131079 - RespProtocol HTTP/1.1 - RespStatus 200 - RespReason OK - RespReason Purged - VCL_call SYNTH - RespHeader Content-Type: text/html; charset=utf-8 - RespHeader Retry-After: 5 - VCL_return deliver - Timestamp Process: 1733554258.896488 0.000256 0.000256 - RespHeader Content-Length: 241 - Storage mse s0 - RespHeader Accept-Ranges: bytes - RespHeader Connection: keep-alive - Timestamp Resp: 1733554258.897431 0.001198 0.000942 - ReqAcct 74 0 74 219 241 460
  • 58.
  • 59.
    <field> <operator> <arg>[&& <field> <oper> <arg> ...] BAN EXPRESSIONS MATCH MULTIPLE OBJECTS
  • 60.
    req.url == /&& req.http.host == example.com obj.status == 404 obj.http.Content-Type ~ ^image/ req.url ~ ^/products(/.+|$) && req.http.host == example.com
  • 61.
    $ varnishadm ban"obj.http.Content-Type ~ ^image/"
  • 62.
    acl purge { "localhost"; "127.0.0.1"; "::1"; "172.16.0.0/12"; } subvcl_recv { if (req.method == "PURGE") { if (!client.ip ~ purge) { return (synth(405)); } if (!req.http.x-invalidate-pattern) { return (purge); } ban("req.url ~ ^" + req.http.x-invalidate-pattern + " && req.http.host == " + req.http.host); return (synth(200,"Ban added")); } }
  • 63.
    curl -XPURGE -H"x-invalidate-pattern:/products/" http://localhost
  • 64.
    $ varnishadm ban.list Presentbans: 1603272627.622051 0 - obj.http.Content-Type eq text/css 1603270370.244746 11 C $ varnishadm ban.list Present bans: 1603272627.622051 11 - obj.http.Content-Type eq text/css $ varnishadm ban.list Present bans: 1603272627.622051 11 C obj.http.Content-Type eq text/css
  • 65.
    $ varnishstat -1-f MAIN.bans MAIN.bans 1 . Count of bans
  • 68.
    Purge-Cache-Tags: config:block_list config:block.block.olivero_account_menu config:block.block.olivero_search_form_wide config:block.block.olivero_breadcrumbs config:block.block.olivero_content config:block.block.olivero_help config:block.block.olivero_page_title config:block.block.olivero_main_menu config:block.block.olivero_search_form_narrow config:block.block.olivero_messages config:block.block.olivero_primary_admin_actions config:block.block.olivero_primary_local_tasks config:block.block.olivero_secondary_local_tasks config:block.block.olivero_powered config:block.block.olivero_site_branding config:block.block.olivero_syndicateblock_view node_view node:1 config:filter.format.basic_html user:1 local_task config:system.menu.account config:search.settings CACHE_MISS_IF_UNCACHEABLE_HTTP_METHOD:form config:system.menu.main config:system.site rendered http_response config:user.role.anonymous
  • 69.
    $ varnishadm ban.list Presentbans: 1727438962.423744 2 - obj.http.X-Magento-Tags ~ ((^|,)cat_p_1(,|$)) 1727438962.414895 0 C obj.http.X-Magento-Tags ~ .* 1727273313.798067 1681 C X-Magento-Tags: store,cms_b,cms_b_1,cms_b_footer_links_block,cat_p_1,cat_p,cat_p_6,cat_p _3,cat_p_4,cat_p_5,cat_p_7,cat_p_12,cat_p_14,cat_p_13,review_block PURGE / HTTP/1.1 Host: localhost X-Magento-Tags-Pattern: ((^|,)cat_p_1(,|$)) PURGE / HTTP/1.1 Host: localhost X-Magento-Tags-Pattern: .*
  • 70.
    $ varnishadm ban.list Presentbans: 1727438962.423744 2 - obj.http.X-Magento-Tags ~ ((^|,)cat_p_1(,|$)) 1727438962.414895 0 C obj.http.X-Magento-Tags ~ .* 1727273313.798067 1681 C THE BAN LURKER THREAD PROCESSES THE BAN LIST
  • 71.
    obj.http.Content-Type ~ ^image/ req.url~ ^/products(/.+|$) && req.http.host == example.com NOT LURKER FRIENDLY LURKER FRIENDLY
  • 72.
    sub vcl_backend_response { setberesp.http.url = bereq.url; set beresp.http.host = bereq.http.host; } sub vcl_deliver { unset resp.http.url; unset resp.http.host; } INJECT REQUEST INFORMATION
  • 73.
    acl purge { "localhost"; "127.0.0.1"; "::1"; "172.16.0.0/12"; } subvcl_recv { if (req.method == "PURGE") { if (!client.ip ~ purge) { return (synth(405)); } if (!req.http.x-invalidate-pattern) { return (purge); } ban("obj.http.url ~ " + req.http.x-invalidate-pattern + " && obj.http.host == " + req.http.host); return (synth(200,"Ban added")); } }
  • 74.
    ban("obj.http.url ~ "+ req.http.x-invalidate-pattern + " && obj.http.host == " + req.http.host); varnishadm ban obj.http.url ~ /products && obj.http.host == example.com
  • 75.
    varnishlog -g request-q "ReqMethod eq 'PURGE'"
  • 76.
    * << Request>> 65538 - Begin req 65537 rxreq - Timestamp Start: 1733555192.617397 0.000000 0.000000 - Timestamp Req: 1733555192.617397 0.000000 0.000000 - VCL_use boot - ReqStart 172.19.0.3 60574 http - ReqMethod PURGE - ReqURL / - ReqProtocol HTTP/1.1 - ReqHeader Host: varnish - ReqHeader user-agent: purge_purger_http module for Drupal 8. - ReqHeader purge-cache-tags: node_list,node_list:page,node:1 - ReqHeader X-Forwarded-For: 172.19.0.3 - ReqHeader Via: 1.1 fddab3bb8c94 (Varnish/7.6) - VCL_call RECV - ReqHeader Surrogate-Capability: Varnish=ESI/1.0 - ReqUnset Host: varnish - ReqHeader Host: varnish - ReqURL / - ReqHeader X-Forwarded-Proto: http - VCL_return synth - VCL_call HASH - VCL_return lookup
  • 77.
    - RespProtocol HTTP/1.1 -RespStatus 200 - RespReason Ban added. - RespHeader Date: Sat, 07 Dec 2024 07:06:32 GMT - RespHeader Server: Varnish - RespHeader X-Varnish: 65538 - VCL_call SYNTH - RespHeader Content-Type: text/html; charset=utf-8 - RespHeader Retry-After: 5 - VCL_return deliver - Timestamp Process: 1733555192.620607 0.003209 0.003209 - RespHeader Content-Length: 252 - Storage malloc Transient - Filters - RespHeader Connection: keep-alive - Timestamp Resp: 1733555192.620675 0.003278 0.000068 - ReqAcct 136 0 136 200 252 452 - End
  • 78.
    Σ BANS XΣ OBJECTS = ⏳
  • 79.
  • 80.
    X-Magento-Tags: store,cms_b,cms_b_1,cms_b_footer_links_block,cat_p_1,cat_p,cat_p_6,cat_p _3,cat_p_4,cat_p_5,cat_p_7,cat_p_12,cat_p_14,cat_p_13,review_block MAGENTO USES TAGS (AB)USES BANS DUETO LACK OF TAG SUPPORT IN VARNISH $ varnishadm ban.list Present bans: 1727438962.423744 2 - obj.http.X-Magento-Tags ~ ((^|,)cat_p_1(,|$))
  • 81.
    import ykey; sub vcl_backend_response{ ykey.add_header(beresp.http.Purge-Cache-Tags, sep=" "); unset beresp.http.Purge-Cache-Tags; ykey.add_key("everything"); if(beresp.http.Content-Type ~ "^image/") { ykey.add_key("image"); } }
  • 82.
    -- BerespHeader Purge-Cache-Tags:config:block_list config:block.block.olivero_account_menu config:block.block.olivero_search_form_wide config:block.block.olivero_breadcrumbs config:block.block.olivero_content config:block.block.olivero_help config:block.block.olivero_page_title config:block.block.olivero_main_menu config:block.block.olivero_search_form_narrow config:block.block.olivero_messages config:block.block.olivero_primary_admin_actions config:block.block.olivero_primary_local_tasks config:block.block.olivero_secondary_local_tasks config:block.block.olivero_powered config:block.block.olivero_site_branding config:block.block.olivero_syndicate block_view node_view node:1 config:filter.format.basic_html user:1 local_task config:system.menu.account config:search.settings CACHE_MISS_IF_UNCACHEABLE_HTTP_METHOD:form config:system.menu.main config:system.site rendered http_response config:user.role.anonymous -- YKEY key: ADD config:block_list -- YKEY key: ADD config:block.block.olivero_account_menu -- YKEY key: ADD config:block.block.olivero_search_form_wide -- YKEY key: ADD config:block.block.olivero_breadcrumbs -- YKEY key: ADD config:block.block.olivero_content -- YKEY key: ADD config:block.block.olivero_help -- YKEY key: ADD config:block.block.olivero_page_title -- YKEY key: ADD config:block.block.olivero_main_menu -- YKEY key: ADD config:block.block.olivero_search_form_narrow -- YKEY key: ADD config:block.block.olivero_messages -- YKEY key: ADD config:block.block.olivero_primary_admin_actions -- YKEY key: ADD config:block.block.olivero_primary_local_tasks -- YKEY key: ADD config:block.block.olivero_secondary_local_tasks -- YKEY key: ADD config:block.block.olivero_powered -- YKEY key: ADD config:block.block.olivero_site_branding -- YKEY key: ADD config:block.block.olivero_syndicate
  • 83.
    -- YKEY key:ADD block_view -- YKEY key: ADD node_view -- YKEY key: ADD node:1 -- YKEY key: ADD config:filter.format.basic_html -- YKEY key: ADD user:1 -- YKEY key: ADD local_task -- YKEY key: ADD config:system.menu.account -- YKEY key: ADD config:search.settings -- YKEY key: ADD CACHE_MISS_IF_UNCACHEABLE_HTTP_METHOD:form -- YKEY key: ADD config:system.menu.main -- YKEY key: ADD config:system.site -- YKEY key: ADD rendered -- YKEY key: ADD http_response -- YKEY key: ADD config:user.role.anonymous -- BerespUnset Purge-Cache-Tags -- YKEY key: ADD everything
  • 84.
    import ykey; acl purge{ "localhost"; "127.0.0.1"; "::1"; } sub vcl_recv { if(req.method == "PURGE") { if(!client.ip ~ purge) { return(synth(405)); } if (req.http.Purge-Cache-Tags) { return (synth(200, ykey.purge_header(req.http.Purge-Cache-Tags, sep=",") + " objects purged")); } return(purge); } }
  • 85.
  • 86.
    * << Request>> 65538 - Begin req 65537 rxreq - Timestamp Start: 1733556901.729447 0.000000 0.000000 - Timestamp Req: 1733556901.729447 0.000000 0.000000 - ReqStart 172.19.0.3 35294 a0 - ReqMethod PURGE - ReqURL / - ReqProtocol HTTP/1.1 - ReqHeader Host: varnish - ReqHeader user-agent: purge_purger_http module for Drupal 8. - ReqHeader purge-cache-tags: node_list,node_list:page,node:1 - ReqHeader X-Forwarded-For: 172.19.0.3 - VCL_call RECV - ReqHeader Surrogate-Capability: Varnish=ESI/1.0 - ReqURL / - ReqURL / - ReqHeader X-Forwarded-Proto: http - VCL_acl MATCH purge "172.16.0.0/12" - YKEY key: PURGE node_list - YKEY key: PURGE node_list:page - YKEY key: PURGE node:1 - VCL_return synth - VCL_call HASH - VCL_return lookup
  • 87.
    - RespHeader Date:Sat, 07 Dec 2024 07:35:01 GMT - RespHeader Server: Varnish - RespHeader X-Varnish: 65538 - RespProtocol HTTP/1.1 - RespStatus 200 - RespReason OK - RespReason 1 objects purged - VCL_call SYNTH - RespHeader Content-Type: text/html; charset=utf-8 - RespHeader Retry-After: 5 - VCL_return deliver - Timestamp Process: 1733556901.733476 0.004029 0.004029 - RespHeader Content-Length: 270 - Storage mse s0 - RespHeader Accept-Ranges: bytes - RespHeader Connection: keep-alive - Timestamp Resp: 1733556901.733543 0.004096 0.000067 - ReqAcct 136 0 136 228 270 498 - End
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
    USER VARNISH SERVER ASYNCFETCH SEND STALE RESPONSE WHILE FETCHING
  • 94.
    OBJECT LIFETIME =TTL + GRACE + KEEP
  • 95.
    OBJECT LIFETIME =TTL + GRACE + KEEP DEFAULT VALUE: 2 MINUTES
  • 96.
    OBJECT LIFETIME =TTL + GRACE + KEEP SERVE STALE CONTENT, ASYNC REVALIDATION DEFAULT VALUE: 10 SECONDS CAN BE SET BY "STALE-WHILE- REVALIDATE"
  • 97.
    OBJECT LIFETIME =TTL + GRACE + KEEP KEEP THE OBJECT AROUND FOR LATER USE DEFAULT VALUE: 0 SECONDS SYNCHRONOUS REVALIDATION
  • 98.
    OBJECT LIFETIME =TTL + GRACE + KEEP SOFT PURGING SETS TTL TO ZERO
  • 99.
    sub vcl_backend_response { setberesp.grace = 1d; }
  • 100.
    import ykey; sub vcl_backend_response{ ykey.add_header(beresp.http.Purge-Cache-Tags, sep=" "); unset beresp.http.Purge-Cache-Tags; ykey.add_key("everything"); if(beresp.http.Content-Type ~ "^image/") { ykey.add_key("image"); } set beresp.grace = 1d; }
  • 101.
    Cache-Control: max-age=60, public,stale-while-revalidate=86400
  • 102.
    - VCL_call HASH -VCL_return lookup - Hit 32775 -25.943176 7200.000000 0.000000 - VCL_call HIT - VCL_return deliver - Link bereq 34 bgfetch
  • 103.
    $ varnishstat -1-f MAIN.cache_hit_grace MAIN.cache_hit_grace 1 Cache grace hits
  • 104.
  • 105.
    FIND THE RIGHT FRAMEWORKPLUGIN OR INTEGRATE PURGING YOURSELF