title: Varnish MISS on some URL's, but HITS on other
body: <p>We are using Magento 2 with Varnish cache</p>
  <p>We only get Varnish Cache HIT on very few /catalogsearch/result/ pages, and we really can not figure out why we don't get cache HIT on all /catalogsearch/result/ pages.</p>
  <p>Please help us in the right direction :-)</p>
  <p>Ex.</p>
  <p>we always get HIT on this url</p>
  <ul>
  <li><a href="https://www.babygear.dk/catalogsearch/result/?q=bog" rel="nofollow noreferrer">https://www.babygear.dk/catalogsearch/result/?q=bog</a></li>
  </ul>
  <p>We always get MISS on a lot of other search queries</p>
  <ul>
  <li><a href="https://www.babygear.dk/catalogsearch/result/?q=black" rel="nofollow noreferrer">https://www.babygear.dk/catalogsearch/result/?q=black</a>
  <a href="https://www.babygear.dk/catalogsearch/result/?q=box" rel="nofollow noreferrer">https://www.babygear.dk/catalogsearch/result/?q=box</a>
  <a href="https://www.babygear.dk/catalogsearch/result/?q=box" rel="nofollow noreferrer">https://www.babygear.dk/catalogsearch/result/?q=box</a></li>
  </ul>
  <p>Here is our varnish.vlc</p>
  <pre><code># VCL version 5.0 is not supported so it should be 4.0 even though actually used Varnish version is 5
  vcl 4.0;
  
  import std;
  # The minimal Varnish version is 5.0
  # For SSL offloading, pass the following header in your proxy server or load balancer: 'X-Forwarded-Proto: https'
  
  backend default {
      .host = &quot;127.0.0.1&quot;;
      .port = &quot;8080&quot;;
      .first_byte_timeout = 600s;
  }
  
  acl purge {
      &quot;127.0.0.1&quot;;
  }
  
  sub vcl_recv {
  
  
      if (req.method == &quot;PURGE&quot;) {
          if (client.ip !~ purge) {
              return (synth(405, &quot;Method not allowed&quot;));
          }
          # To use the X-Pool header for purging varnish during automated deployments, make sure the X-Pool header
          # has been added to the response in your backend server config. This is used, for example, by the
          # capistrano-magento2 gem for purging old content from varnish during it's deploy routine.
          if (!req.http.X-Magento-Tags-Pattern &amp;&amp; !req.http.X-Pool) {
              return (synth(400, &quot;X-Magento-Tags-Pattern or X-Pool header required&quot;));
          }
          if (req.http.X-Magento-Tags-Pattern) {
            ban(&quot;obj.http.X-Magento-Tags ~ &quot; + req.http.X-Magento-Tags-Pattern);
          }
          if (req.http.X-Pool) {
            ban(&quot;obj.http.X-Pool ~ &quot; + req.http.X-Pool);
          }
          return (synth(200, &quot;Purged&quot;));
      }
  
      if (req.method != &quot;GET&quot; &amp;&amp;
          req.method != &quot;HEAD&quot; &amp;&amp;
          req.method != &quot;PUT&quot; &amp;&amp;
          req.method != &quot;POST&quot; &amp;&amp;
          req.method != &quot;TRACE&quot; &amp;&amp;
          req.method != &quot;OPTIONS&quot; &amp;&amp;
          req.method != &quot;DELETE&quot;) {
            /* Non-RFC2616 or CONNECT which is weird. */
            return (pipe);
      }
  
      # We only deal with GET and HEAD by default
      if (req.method != &quot;GET&quot; &amp;&amp; req.method != &quot;HEAD&quot;) {
          return (pass);
      }
  
  
      # Bypass shopping cart, checkout
      if (req.url ~ &quot;/checkout&quot;) {
      return (pass);
      }
      
      # Bypass health check requests
      if (req.url ~ &quot;/pub/health_check.php&quot;) {
          return (pass);
      }
  
      # Set initial grace period usage status
      set req.http.grace = &quot;none&quot;;
  
      # normalize url in case of leading HTTP scheme and domain
      set req.url = regsub(req.url, &quot;^http[s]?://&quot;, &quot;&quot;);
  
      # collect all cookies
      std.collect(req.http.Cookie);
  
      # Compression filter. See https://www.varnish-cache.org/trac/wiki/FAQ/Compression
      if (req.http.Accept-Encoding) {
          if (req.url ~ &quot;\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$&quot;) {
              # No point in compressing these
              unset req.http.Accept-Encoding;
          } elsif (req.http.Accept-Encoding ~ &quot;gzip&quot;) {
              set req.http.Accept-Encoding = &quot;gzip&quot;;
          } elsif (req.http.Accept-Encoding ~ &quot;deflate&quot; &amp;&amp; req.http.user-agent !~ &quot;MSIE&quot;) {
              set req.http.Accept-Encoding = &quot;deflate&quot;;
          } else {
              # unknown algorithm
              unset req.http.Accept-Encoding;
          }
      }
  
      # Remove all marketing get parameters to minimize the cache objects
      if (req.url ~ &quot;(\?|&amp;)(gclid|ff|fp|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=&quot;) {
          set req.url = regsuball(req.url, &quot;(gclid|ff|fp|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&amp;?&quot;, &quot;&quot;);
          set req.url = regsub(req.url, &quot;[?|&amp;]+$&quot;, &quot;&quot;);
      }
  
      # Static files caching
      if (req.url ~ &quot;^/(pub/)?(media|static)/&quot;) {
          # Static files should not be cached by default
          #return (pass);
  
          # But if you use a few locales and don't use CDN you can enable caching static files by commenting previous line (#return (pass);) and uncommenting next 3 lines
          unset req.http.Https;
          unset req.http.X-Forwarded-Proto;
          unset req.http.Cookie;
      }
  
      return (hash);
  }
  
  sub vcl_hash {
      if (req.http.cookie ~ &quot;X-Magento-Vary=&quot;) {
          hash_data(regsub(req.http.cookie, &quot;^.*?X-Magento-Vary=([^;]+);*.*$&quot;, &quot;\1&quot;));
      }
  
      # For multi site configurations to not cache each other's content
      if (req.http.host) {
          hash_data(req.http.host);
      } else {
          hash_data(server.ip);
      }
  
      # To make sure http users don't see ssl warning
      if (req.http.X-Forwarded-Proto) {
          hash_data(req.http.X-Forwarded-Proto);
      }
   
      if (req.url ~ &quot;/graphql&quot;) {
          call process_graphql_headers;
      }
      
  
  }
  
  sub process_graphql_headers {
      if (req.http.Store) {
          hash_data(req.http.Store);
      }
      if (req.http.Content-Currency) {
          hash_data(req.http.Content-Currency);
      }
  }
  
  sub vcl_backend_response {
  
      set beresp.grace = 3d;
  
      if (beresp.http.content-type ~ &quot;text&quot;) {
          set beresp.do_esi = true;
      }
  
      if (bereq.url ~ &quot;\.js$&quot; || beresp.http.content-type ~ &quot;text&quot;) {
          set beresp.do_gzip = true;
      }
  
      if (beresp.http.X-Magento-Debug) {
          set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control;
      }
  
      # cache only successfully responses
      if (beresp.status != 200) {
          set beresp.ttl = 0s;
          set beresp.uncacheable = true;
          return (deliver);
      } elsif (beresp.http.Cache-Control ~ &quot;private&quot;) {
          set beresp.uncacheable = true;
          set beresp.ttl = 44400s;
          return (deliver);
      }
  
      # validate if we need to cache it and prevent from setting cookie
      if (beresp.ttl &gt; 0s &amp;&amp; (bereq.method == &quot;GET&quot; || bereq.method == &quot;HEAD&quot;)) {
          unset beresp.http.set-cookie;
      }
  
  
  
     # If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass
     if (beresp.ttl &lt;= 0s ||
         beresp.http.Surrogate-control ~ &quot;no-store&quot; ||
         (!beresp.http.Surrogate-Control &amp;&amp;
         beresp.http.Cache-Control ~ &quot;no-cache|no-store&quot;) ||
         beresp.http.Vary == &quot;*&quot;) {
          # Mark as Hit-For-Pass for the next 2 minutes
          set beresp.ttl = 120s;
          set beresp.uncacheable = true;
      }
  
      return (deliver);
  }
  
  sub vcl_deliver {
      if (resp.http.X-Magento-Debug) {
          if (resp.http.x-varnish ~ &quot; &quot;) {
              set resp.http.X-Magento-Cache-Debug = &quot;HIT&quot;;
              set resp.http.Grace = req.http.grace;
          } else {
              set resp.http.X-Magento-Cache-Debug = &quot;MISS&quot;;
          }
      } #else {
        #  unset resp.http.Age;
     # }
  
      # Not letting browser to cache non-static files.
      if (resp.http.Cache-Control !~ &quot;private&quot; &amp;&amp; req.url !~ &quot;^/(pub/)?(media|static)/&quot;) {
          set resp.http.Pragma = &quot;no-cache&quot;;
          set resp.http.Expires = &quot;-1&quot;;
          set resp.http.Cache-Control = &quot;no-store, no-cache, must-revalidate, max-age=0&quot;;
      }
  
      unset resp.http.X-Magento-Debug;
      unset resp.http.X-Magento-Tags;
      unset resp.http.X-Powered-By;
      unset resp.http.Server;
      unset resp.http.X-Varnish;
      unset resp.http.Via;
      unset resp.http.Link;
  }
  
  sub vcl_hit {
      if (obj.ttl &gt;= 0s) {
          # Hit within TTL period
          return (deliver);
      }
      if (std.healthy(req.backend_hint)) {
          if (obj.ttl + 3000000s &gt; 0s) {
              # Hit after TTL expiration, but within grace period
              set req.http.grace = &quot;normal (healthy server)&quot;;
              return (deliver);
          } else {
              # Hit after TTL and grace expiration
              return (miss);
          }
      } else {
          # server is not healthy, retrieve from cache
          set req.http.grace = &quot;unlimited (unhealthy server)&quot;;
          return (deliver);
      }
  }
  </code></pre>