{"id":3746,"date":"2025-12-30T16:03:25","date_gmt":"2025-12-30T13:03:25","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/setting-up-varnish-cache-in-front-of-nginx-apache-for-serious-performance-gains\/"},"modified":"2025-12-30T16:03:25","modified_gmt":"2025-12-30T13:03:25","slug":"setting-up-varnish-cache-in-front-of-nginx-apache-for-serious-performance-gains","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/setting-up-varnish-cache-in-front-of-nginx-apache-for-serious-performance-gains\/","title":{"rendered":"Setting Up Varnish Cache in Front of Nginx\/Apache for Serious Performance Gains"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><p>If you run a busy WordPress, WooCommerce, Laravel or custom PHP site, you eventually hit the same wall: PHP and the database become the bottleneck. You add OPcache, tune MySQL, maybe even move to a faster NVMe <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a>, yet under peak load your application server still struggles. At that point, putting a powerful HTTP cache in front of your web server is often the single biggest win you can get. That is exactly where Varnish Cache shines as a reverse proxy in front of Nginx or Apache.<\/p>\n<p>In this guide we will walk through how Varnish works, how to place it in front of Nginx or Apache on a VPS or <a href=\"https:\/\/www.dchost.com\/dedicated-server\">dedicated server<\/a>, and how to tune it so it actually boosts performance for real applications instead of randomly serving stale HTML. We will combine practical configuration snippets with architectural tips, and we will also look at how to measure the real gains in requests per second, TTFB and Core Web Vitals. All examples are written from the perspective of how we design and operate stacks at dchost.com, so you can reuse the same patterns on your own infrastructure.<\/p>\n<div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#Why_Put_Varnish_in_Front_of_Nginx_or_Apache\"><span class=\"toc_number toc_depth_1\">1<\/span> Why Put Varnish in Front of Nginx or Apache?<\/a><\/li><li><a href=\"#How_Varnish_Works_as_a_Reverse_Proxy\"><span class=\"toc_number toc_depth_1\">2<\/span> How Varnish Works as a Reverse Proxy<\/a><ul><li><a href=\"#Basic_request_flow\"><span class=\"toc_number toc_depth_2\">2.1<\/span> Basic request flow<\/a><\/li><li><a href=\"#VCL_the_brain_of_Varnish\"><span class=\"toc_number toc_depth_2\">2.2<\/span> VCL: the brain of Varnish<\/a><\/li><li><a href=\"#What_Varnish_does_and_does_not_do\"><span class=\"toc_number toc_depth_2\">2.3<\/span> What Varnish does (and does not) do<\/a><\/li><\/ul><\/li><li><a href=\"#Planning_Your_Varnish_NginxApache_Architecture\"><span class=\"toc_number toc_depth_1\">3<\/span> Planning Your Varnish + Nginx\/Apache Architecture<\/a><ul><li><a href=\"#Scenario_1_Simple_HTTP_stack_on_a_single_VPS\"><span class=\"toc_number toc_depth_2\">3.1<\/span> Scenario 1: Simple HTTP stack on a single VPS<\/a><\/li><li><a href=\"#Scenario_2_TLS_termination_in_Nginx_Varnish_behind_it\"><span class=\"toc_number toc_depth_2\">3.2<\/span> Scenario 2: TLS termination in Nginx, Varnish behind it<\/a><\/li><li><a href=\"#Scenario_3_CDN_in_front_Varnish_in_the_origin\"><span class=\"toc_number toc_depth_2\">3.3<\/span> Scenario 3: CDN in front, Varnish in the origin<\/a><\/li><li><a href=\"#Ports_and_processes\"><span class=\"toc_number toc_depth_2\">3.4<\/span> Ports and processes<\/a><\/li><\/ul><\/li><li><a href=\"#Installing_Varnish_on_a_Typical_Linux_VPS\"><span class=\"toc_number toc_depth_1\">4<\/span> Installing Varnish on a Typical Linux VPS<\/a><ul><li><a href=\"#Step_1_Install_Varnish\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Step 1: Install Varnish<\/a><\/li><li><a href=\"#Step_2_Reconfigure_Nginx_to_run_on_8080\"><span class=\"toc_number toc_depth_2\">4.2<\/span> Step 2: Reconfigure Nginx to run on 8080<\/a><\/li><li><a href=\"#Step_3_Point_Varnish_to_Nginx_as_backend\"><span class=\"toc_number toc_depth_2\">4.3<\/span> Step 3: Point Varnish to Nginx as backend<\/a><\/li><li><a href=\"#Step_4_Make_Varnish_listen_on_port_80\"><span class=\"toc_number toc_depth_2\">4.4<\/span> Step 4: Make Varnish listen on port 80<\/a><\/li><li><a href=\"#Example_with_Apache_as_backend\"><span class=\"toc_number toc_depth_2\">4.5<\/span> Example with Apache as backend<\/a><\/li><\/ul><\/li><li><a href=\"#Tuning_Varnish_for_Real-World_Apps\"><span class=\"toc_number toc_depth_1\">5<\/span> Tuning Varnish for Real-World Apps<\/a><ul><li><a href=\"#Basic_cache_rules_in_VCL\"><span class=\"toc_number toc_depth_2\">5.1<\/span> Basic cache rules in VCL<\/a><\/li><li><a href=\"#Microcaching_vs_long_TTLs\"><span class=\"toc_number toc_depth_2\">5.2<\/span> Microcaching vs long TTLs<\/a><\/li><li><a href=\"#Handling_cookies_correctly\"><span class=\"toc_number toc_depth_2\">5.3<\/span> Handling cookies correctly<\/a><\/li><li><a href=\"#Bypassing_sensitive_paths\"><span class=\"toc_number toc_depth_2\">5.4<\/span> Bypassing sensitive paths<\/a><\/li><li><a href=\"#Static_assets_let_Nginx_shine\"><span class=\"toc_number toc_depth_2\">5.5<\/span> Static assets: let Nginx shine<\/a><\/li><\/ul><\/li><li><a href=\"#Measuring_and_Proving_Performance_Gains\"><span class=\"toc_number toc_depth_1\">6<\/span> Measuring and Proving Performance Gains<\/a><ul><li><a href=\"#1_Baseline_your_site_before_enabling_Varnish\"><span class=\"toc_number toc_depth_2\">6.1<\/span> 1. Baseline your site before enabling Varnish<\/a><\/li><li><a href=\"#2_Check_cache_hit_ratio\"><span class=\"toc_number toc_depth_2\">6.2<\/span> 2. Check cache hit ratio<\/a><\/li><li><a href=\"#3_Load-test_with_and_without_Varnish\"><span class=\"toc_number toc_depth_2\">6.3<\/span> 3. Load-test with and without Varnish<\/a><\/li><li><a href=\"#4_Watch_Core_Web_Vitals\"><span class=\"toc_number toc_depth_2\">6.4<\/span> 4. Watch Core Web Vitals<\/a><\/li><\/ul><\/li><li><a href=\"#When_Varnish_Is_and_Isn039t_a_Good_Idea\"><span class=\"toc_number toc_depth_1\">7<\/span> When Varnish Is (and Isn&#039;t) a Good Idea<\/a><ul><li><a href=\"#Great_use_cases_for_Varnish\"><span class=\"toc_number toc_depth_2\">7.1<\/span> Great use cases for Varnish<\/a><\/li><li><a href=\"#Less_ideal_or_advanced_scenarios\"><span class=\"toc_number toc_depth_2\">7.2<\/span> Less ideal or advanced scenarios<\/a><\/li><\/ul><\/li><li><a href=\"#Putting_It_All_Together_on_dchostcom_Infrastructure\"><span class=\"toc_number toc_depth_1\">8<\/span> Putting It All Together on dchost.com Infrastructure<\/a><\/li><li><a href=\"#Summary_and_Next_Steps\"><span class=\"toc_number toc_depth_1\">9<\/span> Summary and Next Steps<\/a><\/li><\/ul><\/div>\n<h2><span id=\"Why_Put_Varnish_in_Front_of_Nginx_or_Apache\">Why Put Varnish in Front of Nginx or Apache?<\/span><\/h2>\n<p>Varnish is a high-performance HTTP accelerator designed to sit between clients (browsers, bots, APIs) and your origin web server. Instead of every request hitting PHP and the database, Varnish stores rendered pages in memory and serves them directly until they expire or are purged.<\/p>\n<p>When deployed correctly as a reverse proxy, Varnish can:<\/p>\n<ul>\n<li><strong>Increase requests per second<\/strong> by 5\u201350x for cacheable pages, because responses come directly from RAM instead of PHP\/MySQL.<\/li>\n<li><strong>Reduce TTFB<\/strong> from 400\u2013800 ms down to 20\u201350 ms for cached responses.<\/li>\n<li><strong>Flatten traffic spikes<\/strong> during campaigns or news events; instead of hammering PHP, thousands of concurrent users are served from cache.<\/li>\n<li><strong>Lower CPU and I\/O usage<\/strong> on your Nginx\/Apache+PHP stack, giving more headroom for dynamic operations like checkout, dashboards or APIs.<\/li>\n<\/ul>\n<p>We often pair Varnish with other optimizations like <a href=\"https:\/\/www.dchost.com\/blog\/en\/php-opcache-ayarlari-wordpress-laravel-ve-woocommerce-icin-en-iyi-konfigurasyon-rehberi\/\">correct PHP OPcache settings for WordPress and Laravel<\/a>, tuned MySQL, and NVMe storage. When that combination is built on a properly sized VPS or dedicated server, the performance jump is dramatic.<\/p>\n<h2><span id=\"How_Varnish_Works_as_a_Reverse_Proxy\">How Varnish Works as a Reverse Proxy<\/span><\/h2>\n<p>Before touching any configuration, it is important to understand how Varnish fits into the request flow and how its caching logic works.<\/p>\n<h3><span id=\"Basic_request_flow\">Basic request flow<\/span><\/h3>\n<p>In a simple Varnish+Nginx setup, the flow typically looks like this:<\/p>\n<ul>\n<li>The client sends an HTTP request to your server&#039;s IP on port 80.<\/li>\n<li>Varnish listens on port 80 and receives the request.<\/li>\n<li>Varnish decides whether the request is cacheable, can be served from cache, or must go to the backend.<\/li>\n<li>If cached, Varnish serves the response directly from memory.<\/li>\n<li>If not cached, Varnish forwards the request to Nginx\/Apache (the <strong>backend<\/strong>), typically listening on 8080 or 8081.<\/li>\n<li>Nginx\/Apache processes the request (including PHP, database, etc.) and returns a response to Varnish.<\/li>\n<li>Varnish optionally stores the response in cache according to rules (TTL, Cache-Control headers, cookies), then sends it back to the client.<\/li>\n<\/ul>\n<h3><span id=\"VCL_the_brain_of_Varnish\">VCL: the brain of Varnish<\/span><\/h3>\n<p>Varnish is controlled by a configuration language called <strong>VCL (Varnish Configuration Language)<\/strong>. With VCL you:<\/p>\n<ul>\n<li>Define backends (e.g. your Nginx or Apache instance).<\/li>\n<li>Decide which URLs, methods and cookies should be cached.<\/li>\n<li>Implement cache bypass rules for logged-in users or cart pages.<\/li>\n<li>Control TTLs, grace periods, and how to handle errors.<\/li>\n<\/ul>\n<p>If you are already comfortable writing Nginx configs or Apache vhosts, VCL will feel different but not scary: it is more like a mini-programming language for HTTP caching decisions.<\/p>\n<h3><span id=\"What_Varnish_does_and_does_not_do\">What Varnish does (and does not) do<\/span><\/h3>\n<ul>\n<li>Varnish <strong>does<\/strong> cache HTTP responses and handle routing to backends.<\/li>\n<li>Varnish <strong>does not<\/strong> handle HTTPS\/TLS on its own. In production you usually terminate TLS with Nginx\/Apache, HAProxy or Hitch and put Varnish behind that, or you put Varnish behind a CDN that does TLS.<\/li>\n<li>Varnish is <strong>not<\/strong> a WAF or rate limiter; for that we usually rely on Nginx rules, ModSecurity, or external services. See our <a href=\"https:\/\/www.dchost.com\/blog\/en\/cloudflare-guvenlik-ayarlari-rehberi-kucuk-isletme-siteleri-icin-waf-rate-limit-ve-bot-korumasi\/\">Cloudflare security settings guide<\/a> for examples of combining caching with WAF and bot protection.<\/li>\n<\/ul>\n<h2><span id=\"Planning_Your_Varnish_NginxApache_Architecture\">Planning Your Varnish + Nginx\/Apache Architecture<\/span><\/h2>\n<p>There are a few realistic ways to arrange Varnish with Nginx or Apache. The &quot;right&quot; choice depends on where you terminate HTTPS and whether you also use a CDN.<\/p>\n<h3><span id=\"Scenario_1_Simple_HTTP_stack_on_a_single_VPS\">Scenario 1: Simple HTTP stack on a single VPS<\/span><\/h3>\n<p>This is the easiest starting point for labs, staging, or internal applications without public TLS:<\/p>\n<ul>\n<li>Client \u2192 Varnish on port 80<\/li>\n<li>Varnish \u2192 Nginx\/Apache backend on port 8080<\/li>\n<\/ul>\n<p>Nginx\/Apache serves only HTTP internally. You do not expose it to the internet directly; Varnish is the single entry point.<\/p>\n<h3><span id=\"Scenario_2_TLS_termination_in_Nginx_Varnish_behind_it\">Scenario 2: TLS termination in Nginx, Varnish behind it<\/span><\/h3>\n<p>Because Varnish does not speak TLS, a very common production pattern is:<\/p>\n<ul>\n<li>Client \u2192 Nginx (HTTPS 443)<\/li>\n<li>Nginx \u2192 Varnish (HTTP, local port e.g. 6081)<\/li>\n<li>Varnish \u2192 Nginx\/Apache backend (HTTP 8080)<\/li>\n<\/ul>\n<p>Nginx handles SSL\/TLS (including HTTP\/2\/3, HSTS, OCSP stapling, Brotli\/Gzip compression). Varnish then operates on plain HTTP traffic. You can learn more about the HTTPS side in our guides on <a href=\"https:\/\/www.dchost.com\/blog\/en\/http-2-ve-http-3-destegi-seo-ve-core-web-vitalsi-nasil-etkiler-hosting-secerken-nelere-bakmali\/\">HTTP\/2 and HTTP\/3<\/a> and <a href=\"https:\/\/www.dchost.com\/blog\/en\/brotli-ve-gzip-sikistirma-ayarlari-nginx-apache-ve-litespeedde-core-web-vitals-icin-dogru-konfigurasyon\/\">Brotli and Gzip compression settings<\/a>.<\/p>\n<h3><span id=\"Scenario_3_CDN_in_front_Varnish_in_the_origin\">Scenario 3: CDN in front, Varnish in the origin<\/span><\/h3>\n<p>For high-traffic sites we frequently see:<\/p>\n<ul>\n<li>Client \u2192 CDN (TLS, HTTP\/2\/3)<\/li>\n<li>CDN \u2192 Varnish (HTTP or HTTPS, depending on setup)<\/li>\n<li>Varnish \u2192 Nginx\/Apache backend<\/li>\n<\/ul>\n<p>The CDN offloads static assets and some HTML caching at the edge, while Varnish acts as an origin cache layer shielding your app servers. This approach is common for multi-region architectures or when you also use <a href=\"https:\/\/www.dchost.com\/blog\/en\/geodns-ve-cok-bolgeli-hosting-mimarisi-ile-global-ziyaretcilere-yakinlasmak\/\">GeoDNS and multi-region hosting<\/a>.<\/p>\n<h3><span id=\"Ports_and_processes\">Ports and processes<\/span><\/h3>\n<p>A typical single-server layout for Varnish in front of Nginx looks like this:<\/p>\n<ul>\n<li>Varnish listening on <strong>80<\/strong><\/li>\n<li>Nginx listening on <strong>8080<\/strong> (HTTP) and maybe <strong>443<\/strong> (HTTPS) if you terminate TLS there as well<\/li>\n<\/ul>\n<p>For Apache, you do the same: move Apache from 80\/443 to 8080 (and optionally 8443) and let Varnish take 80.<\/p>\n<h2><span id=\"Installing_Varnish_on_a_Typical_Linux_VPS\">Installing Varnish on a Typical Linux VPS<\/span><\/h2>\n<p>The example below assumes an Ubuntu\/Debian VPS or dedicated server from dchost.com or a similar environment where you have root SSH access. The general steps are similar on AlmaLinux\/Rocky with yum\/dnf packages.<\/p>\n<h3><span id=\"Step_1_Install_Varnish\">Step 1: Install Varnish<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo apt update\nsudo apt install varnish\n<\/code><\/pre>\n<p>On Debian\/Ubuntu this will install Varnish and configure it to listen on port 6081 by default.<\/p>\n<h3><span id=\"Step_2_Reconfigure_Nginx_to_run_on_8080\">Step 2: Reconfigure Nginx to run on 8080<\/span><\/h3>\n<p>Edit your Nginx site configuration, for example:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo nano \/etc\/nginx\/sites-available\/default\n<\/code><\/pre>\n<p>Change:<\/p>\n<pre class=\"language-nginx line-numbers\"><code class=\"language-nginx\">server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n    ...\n}\n<\/code><\/pre>\n<p>to:<\/p>\n<pre class=\"language-nginx line-numbers\"><code class=\"language-nginx\">server {\n    listen 8080 default_server;\n    listen [::]:8080 default_server;\n    ...\n}\n<\/code><\/pre>\n<p>Then reload Nginx:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo nginx -t\nsudo systemctl reload nginx\n<\/code><\/pre>\n<h3><span id=\"Step_3_Point_Varnish_to_Nginx_as_backend\">Step 3: Point Varnish to Nginx as backend<\/span><\/h3>\n<p>Edit the main VCL file (path may vary slightly by distribution):<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo nano \/etc\/varnish\/default.vcl\n<\/code><\/pre>\n<p>Set up a backend definition:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">vcl 4.1;\n\nbackend default {\n    .host = &quot;127.0.0.1&quot;;\n    .port = &quot;8080&quot;;\n}\n<\/code><\/pre>\n<p>This tells Varnish to forward all cache misses to Nginx running on localhost:8080.<\/p>\n<h3><span id=\"Step_4_Make_Varnish_listen_on_port_80\">Step 4: Make Varnish listen on port 80<\/span><\/h3>\n<p>On Debian\/Ubuntu, Varnish&#039;s listening port is controlled by the systemd service parameters in <code>\/etc\/systemd\/system\/multi-user.target.wants\/varnish.service<\/code> (or a drop-in file like <code>\/etc\/systemd\/system\/varnish.service.d\/custom.conf<\/code> depending on your version).<\/p>\n<p>Look for a line similar to:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">ExecStart=\/usr\/sbin\/varnishd -a :6081 -T localhost:6082 -f \/etc\/varnish\/default.vcl ...\n<\/code><\/pre>\n<p>Change <code>-a :6081<\/code> to <code>-a :80<\/code>:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">ExecStart=\/usr\/sbin\/varnishd -a :80 -T localhost:6082 -f \/etc\/varnish\/default.vcl ...\n<\/code><\/pre>\n<p>Reload systemd and restart Varnish:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo systemctl daemon-reload\nsudo systemctl restart varnish\n<\/code><\/pre>\n<p>Now Varnish is on port 80, talking to Nginx on 8080. Test with:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">curl -I http:\/\/your-domain.com\n<\/code><\/pre>\n<p>You should see headers like <code>Via: 1.1 varnish<\/code> and <code>X-Varnish:<\/code>, which confirm that Varnish is in the chain.<\/p>\n<h3><span id=\"Example_with_Apache_as_backend\">Example with Apache as backend<\/span><\/h3>\n<p>With Apache, the concept is the same: change Apache to listen on 8080 and let Varnish take port 80.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo nano \/etc\/apache2\/ports.conf\n<\/code><\/pre>\n<p>Modify:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">Listen 80\n<\/code><\/pre>\n<p>to:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">Listen 8080\n<\/code><\/pre>\n<p>Then update your virtual hosts in <code>\/etc\/apache2\/sites-available\/*.conf<\/code> from <code>&lt;VirtualHost *:80&gt;<\/code> to <code>&lt;VirtualHost *:8080&gt;<\/code>, restart Apache, and configure Varnish&#039;s backend to use port 8080 as shown earlier.<\/p>\n<h2><span id=\"Tuning_Varnish_for_Real-World_Apps\">Tuning Varnish for Real-World Apps<\/span><\/h2>\n<p>Simply installing Varnish in front of Nginx\/Apache does not guarantee great performance. The real gains come from dialing in your cache rules so that:<\/p>\n<ul>\n<li>Anonymous traffic is cached aggressively.<\/li>\n<li>Logged-in sessions and carts are not cached (or are microcached safely).<\/li>\n<li>Static assets are either served directly by Nginx or cached long-term by Varnish\/CDN.<\/li>\n<\/ul>\n<p>We already covered full-page caching strategies in our article <a href=\"https:\/\/www.dchost.com\/blog\/en\/wordpresste-tam-sayfa-onbellekleme-nasil-kurulur-nginx-fastcgi-cache-varnish-ve-litespeed-cache-ile-woocommercee-nazikce-dokunmak\/\">Full-page caching for WordPress without breaking WooCommerce<\/a>; here we&#039;ll focus on the Varnish-specific side.<\/p>\n<h3><span id=\"Basic_cache_rules_in_VCL\">Basic cache rules in VCL<\/span><\/h3>\n<p>Extend your <code>default.vcl<\/code> with caching decisions. A common pattern is:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sub vcl_recv {\n    # Only cache GET and HEAD\n    if (req.method != &quot;GET&quot; &amp;&amp; req.method != &quot;HEAD&quot;) {\n        return (pass);\n    }\n\n    # Don&amp;#039;t cache admin or login paths\n    if (req.url ~ &quot;wp-admin&quot; || req.url ~ &quot;wp-login.php&quot;) {\n        return (pass);\n    }\n\n    # Don&amp;#039;t cache when user is logged in (WordPress example)\n    if (req.http.Cookie ~ &quot;wordpress_logged_in_&quot;) {\n        return (pass);\n    }\n}\n\nsub vcl_backend_response {\n    # Only cache HTTP 200 and 301\n    if (beresp.status == 200 || beresp.status == 301) {\n        # Set default TTL if backend didn&amp;#039;t specify\n        if (beresp.ttl &lt;= 0s) {\n            set beresp.ttl = 120s;\n        }\n    } else {\n        set beresp.ttl = 0s;\n    }\n}\n<\/code><\/pre>\n<p>This is intentionally simple but already protects admin\/logged-in users while caching anonymous pages for 2 minutes.<\/p>\n<h3><span id=\"Microcaching_vs_long_TTLs\">Microcaching vs long TTLs<\/span><\/h3>\n<p>For highly dynamic sites (news homepages, fast-changing e-commerce), we often start with <strong>microcaching<\/strong>: storing pages for 1\u201310 seconds. That may sound tiny, but it dramatically reduces the load when many users hit the same URLs simultaneously.<\/p>\n<p>Example:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">set beresp.ttl = 5s;\nset beresp.grace = 30s;\n<\/code><\/pre>\n<p><code>grace<\/code> allows Varnish to serve slightly stale content if the backend is slow or temporarily failing, while it refreshes the cache in the background. This is very effective during short spikes or brief backend hiccups.<\/p>\n<h3><span id=\"Handling_cookies_correctly\">Handling cookies correctly<\/span><\/h3>\n<p>Cookies are often the biggest enemy of caching. Many CMS and ecommerce platforms set unnecessary cookies for analytics or A\/B testing, which can cause Varnish to create separate cache entries per cookie value or bypass the cache entirely.<\/p>\n<p>In VCL, you can remove unnecessary cookies for anonymous users:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sub vcl_recv {\n    # ... existing rules ...\n\n    # For anonymous users, strip analytics cookies so responses can be cached\n    if (!(req.http.Cookie ~ &quot;wordpress_logged_in_&quot;)) {\n        set req.http.Cookie = regsuball(req.http.Cookie,\n            &quot;(?i)(^|;s*)(_ga|_gid|_fbp)=[^;]*&quot;, &quot;&quot;);\n        # Remove empty cookie header\n        if (req.http.Cookie == &quot;&quot; || req.http.Cookie == &quot;;&quot;) {\n            unset req.http.Cookie;\n        }\n    }\n}\n<\/code><\/pre>\n<p>The exact cookie names will depend on your stack, but the idea is to keep only the cookies that truly matter for page variation or sessions.<\/p>\n<h3><span id=\"Bypassing_sensitive_paths\">Bypassing sensitive paths<\/span><\/h3>\n<p>Always bypass caching on:<\/p>\n<ul>\n<li>Login pages<\/li>\n<li>Cart\/checkout steps<\/li>\n<li>Account dashboards<\/li>\n<li>APIs that must always be fresh (e.g. stock levels, personalized feeds)<\/li>\n<\/ul>\n<p>You can do this by matching URL path patterns in <code>vcl_recv<\/code> and returning <code>pass<\/code> early:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">if (req.url ~ &quot;\/cart&quot; || req.url ~ &quot;\/checkout&quot;) {\n    return (pass);\n}\n<\/code><\/pre>\n<h3><span id=\"Static_assets_let_Nginx_shine\">Static assets: let Nginx shine<\/span><\/h3>\n<p>Although Varnish can cache static assets, we often prefer to let Nginx handle them directly with long Cache-Control headers and optionally a CDN in front. Nginx is excellent at serving static files, especially when combined with <a href=\"https:\/\/www.dchost.com\/blog\/en\/brotli-ve-gzip-sikistirma-ayarlari-nginx-apache-ve-litespeedde-core-web-vitals-icin-dogru-konfigurasyon\/\">Brotli or Gzip compression<\/a>.<\/p>\n<p>One practical model:<\/p>\n<ul>\n<li>CDN edge caches images, CSS, JS for days or weeks.<\/li>\n<li>Varnish focuses on HTML pages and maybe some JSON endpoints.<\/li>\n<li>Nginx\/Apache serves static files as the ultimate origin when needed.<\/li>\n<\/ul>\n<h2><span id=\"Measuring_and_Proving_Performance_Gains\">Measuring and Proving Performance Gains<\/span><\/h2>\n<p>It is tempting to declare success as soon as you see <code>Via: 1.1 varnish<\/code> in response headers, but you will only know how much Varnish actually helps if you measure it carefully.<\/p>\n<h3><span id=\"1_Baseline_your_site_before_enabling_Varnish\">1. Baseline your site before enabling Varnish<\/span><\/h3>\n<p>Before you change anything, gather baseline numbers:<\/p>\n<ul>\n<li>TTFB and LCP from PageSpeed Insights, WebPageTest or Lighthouse.<\/li>\n<li>Average response time and RPS from a simple load test (k6, JMeter, wrk).<\/li>\n<li>CPU\/RAM usage on your VPS or dedicated server under moderate load.<\/li>\n<\/ul>\n<p>If you need a refresher on proper speed testing, see our article <a href=\"https:\/\/www.dchost.com\/blog\/en\/web-sitenizin-hizini-dogru-olcmek-gtmetrix-pagespeed-insights-ve-webpagetest-rehberi\/\">how to properly test your website speed<\/a>.<\/p>\n<h3><span id=\"2_Check_cache_hit_ratio\">2. Check cache hit ratio<\/span><\/h3>\n<p>Varnish exposes useful statistics through <code>varnishstat<\/code> and <code>varnishlog<\/code>. A key metric is <strong>cache hit ratio<\/strong> (hits vs misses) for your main pages.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo varnishstat -1 | egrep &quot;MAIN.cache_hit|MAIN.cache_miss&quot;\n<\/code><\/pre>\n<p>Over time, you want to see hits grow much faster than misses for anonymous page requests. If your hit ratio stays low, most likely:<\/p>\n<ul>\n<li>Cookies are preventing caching.<\/li>\n<li>Your TTLs are too short, or Cache-Control headers from the backend forbid caching.<\/li>\n<li>You are bypassing too many URLs in VCL.<\/li>\n<\/ul>\n<h3><span id=\"3_Load-test_with_and_without_Varnish\">3. Load-test with and without Varnish<\/span><\/h3>\n<p>On a staging environment, you can easily compare:<\/p>\n<ul>\n<li>Direct Nginx\/Apache on 8080.<\/li>\n<li>Varnish-fronted stack on 80.<\/li>\n<\/ul>\n<p>Use a load-testing tool (for example k6, which we covered in our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/trafik-patlamasindan-once-load-test-yapmak-k6-jmeter-ve-locust-ile-kapasite-olcme-rehberi\/\">load testing your hosting before traffic spikes<\/a>) and run identical scenarios:<\/p>\n<ul>\n<li>Same URLs<\/li>\n<li>Same number of virtual users<\/li>\n<li>Same duration<\/li>\n<\/ul>\n<p>You should see:<\/p>\n<ul>\n<li>Significantly higher requests per second with Varnish.<\/li>\n<li>Lower and more stable average\/95th percentile response times.<\/li>\n<li>Lower CPU and IO wait on the origin server.<\/li>\n<\/ul>\n<h3><span id=\"4_Watch_Core_Web_Vitals\">4. Watch Core Web Vitals<\/span><\/h3>\n<p>Core Web Vitals (LCP, FID, CLS) are influenced by many factors, but TTFB is a big component of LCP. With a warm Varnish cache and solid server-side tuning (PHP-FPM, OPcache, database), it becomes much easier to keep LCP within Google&#039;s recommended thresholds, especially on mobile connections.<\/p>\n<p>We dive deeper into the hosting side of Core Web Vitals in our article <a href=\"https:\/\/www.dchost.com\/blog\/en\/core-web-vitals-ve-hosting-altyapisi-ttfb-lcp-ve-clsyi-sunucu-tarafinda-iyilestirme-rehberi\/\">how server choices impact TTFB, LCP and CLS<\/a>.<\/p>\n<h2><span id=\"When_Varnish_Is_and_Isn039t_a_Good_Idea\">When Varnish Is (and Isn&#039;t) a Good Idea<\/span><\/h2>\n<p>Varnish is powerful, but it is not a silver bullet for every workload. Here is a realistic view of where it shines and where it might add unnecessary complexity.<\/p>\n<h3><span id=\"Great_use_cases_for_Varnish\">Great use cases for Varnish<\/span><\/h3>\n<ul>\n<li><strong>Content-heavy WordPress\/blog\/news sites<\/strong> with mostly public content. Full-page caching can often handle 90\u201399% of requests.<\/li>\n<li><strong>Marketing and landing-page sites<\/strong> where content changes only at deploys or a few times per day.<\/li>\n<li><strong>Hybrid WooCommerce stores<\/strong> where category\/product pages are cached for anonymous users, and only cart\/checkout remain dynamic.<\/li>\n<li><strong>Multi-tenant apps<\/strong> with shared templates but different hostnames, where Varnish can cache per hostname.<\/li>\n<\/ul>\n<h3><span id=\"Less_ideal_or_advanced_scenarios\">Less ideal or advanced scenarios<\/span><\/h3>\n<ul>\n<li><strong>Heavily personalized dashboards<\/strong> where almost every element is user-specific.<\/li>\n<li><strong>Real-time applications<\/strong> relying on WebSockets or long-lived HTTP connections (chat, streaming data, etc.). Here, using Varnish requires careful exception rules or a different architecture.<\/li>\n<li><strong>Complex APIs<\/strong> where clients depend on real-time responses. Microcaching can help but must be done very carefully.<\/li>\n<\/ul>\n<p>In these cases, start by tuning PHP-FPM, OPcache, and your database first, and consider alternatives like Nginx microcaching or Redis object cache before adding a full Varnish layer.<\/p>\n<h2><span id=\"Putting_It_All_Together_on_dchostcom_Infrastructure\">Putting It All Together on dchost.com Infrastructure<\/span><\/h2>\n<p>On our side, when a customer on a VPS, dedicated server or colocation setup at dchost.com asks for &quot;serious speed&quot; for a PHP-based site, our typical playbook looks like this:<\/p>\n<ol>\n<li>Right-size the server (vCPU, RAM, NVMe storage) for the expected traffic and database size.<\/li>\n<li>Install and tune PHP-FPM and OPcache for the specific application (WordPress, WooCommerce, Laravel, custom PHP).<\/li>\n<li>Optimize MySQL\/MariaDB or PostgreSQL, sometimes adding replication if the workload requires it.<\/li>\n<li>Configure Nginx or Apache properly (keep-alive, compression, HTTP\/2\/3 where relevant).<\/li>\n<li>Add Varnish as a reverse proxy in front of Nginx\/Apache for full-page caching of anonymous traffic.<\/li>\n<li>Optionally place a CDN\/WAF in front for global reach and additional protection.<\/li>\n<\/ol>\n<p>By layering Varnish on top of a cleanly tuned origin stack, we avoid treating caching as a band-aid and instead use it as a force multiplier.<\/p>\n<h2><span id=\"Summary_and_Next_Steps\">Summary and Next Steps<\/span><\/h2>\n<p>Varnish Cache, when deployed as a reverse proxy in front of Nginx or Apache, can transform how your infrastructure behaves under load. Instead of every user hitting PHP and the database, you serve most of your traffic directly from memory with sub-50 ms TTFB, while your origin servers focus on the truly dynamic and personalized parts of your application.<\/p>\n<p>The key steps are straightforward: move Nginx\/Apache to an internal port, point Varnish at it as a backend, tune your VCL to cache anonymous traffic while bypassing sensitive paths and sessions, then measure the gains with real load tests and Core Web Vitals. Combined with proper PHP, database and TLS tuning, you can comfortably absorb traffic spikes and grow without constantly fighting CPU and IO limits.<\/p>\n<p>If you are planning a new project or outgrowing shared hosting, our team at dchost.com can help you design a VPS, dedicated server or colocation architecture that makes the most of Varnish, Nginx\/Apache and your application stack. Whether you want a simple single-server setup or a multi-region origin with CDN and advanced caching rules, you can build on the patterns we have outlined here and adapt them to your own workloads.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>If you run a busy WordPress, WooCommerce, Laravel or custom PHP site, you eventually hit the same wall: PHP and the database become the bottleneck. You add OPcache, tune MySQL, maybe even move to a faster NVMe VPS, yet under peak load your application server still struggles. At that point, putting a powerful HTTP cache [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3747,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-3746","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3746","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/comments?post=3746"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3746\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/3747"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=3746"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=3746"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=3746"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}