title: Nginx microcaching wordpress, why is returning bypass?
body: <p>recently I had to setup AWS ASG environment for Wordpress application. This wordpress is a very common one.</p>
  
  <p>The environment in pre and pro is equal and also the behavior of both. My infrastructure have:</p>
  
  <ul>
  <li>1 ASG</li>
  <li>1 ALB</li>
  <li>m3.medium EC2 instances</li>
  <li>Memcached cluster</li>
  <li>RDS MySQL</li>
  <li>S3 for static content</li>
  </ul>
  
  <p>Stack is a common Nginx / Php 5.6 FPM with microcaching enabled and W3TC to setup cache for database and other stuff.</p>
  
  <p>My nginx.conf is like (I will hide the domain name)</p>
  
  <pre><code>user  nginx;
  worker_processes  auto;
  
  error_log  /var/log/nginx/error.log;
  pid        /var/run/nginx.pid;
  
  events {
          worker_connections 65536;
          use epoll;
          multi_accept on;
  }
  
  http {
      include       /etc/nginx/mime.types;
      default_type  application/octet-stream;
      set_real_ip_from 172.16.0.0/16;
      real_ip_header X-Forwarded-For;
      log_format  main  '$host $remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent"';
  
      access_log  /var/log/nginx/access.log  main;
  
      server_names_hash_max_size 1024;
  
      sendfile on;
      tcp_nopush on;
      tcp_nodelay on;
      server_tokens off;
      keepalive_requests 100000;
      keepalive_timeout  65 20;
  
      gzip on;
      gzip_disable "msie6";
      gzip_vary on;
      gzip_min_length 512;
      gzip_buffers 256 8k;
      gzip_comp_level 6;
      gzip_proxied any;
      gzip_types text/plain test/html text/xml text/css image/x-icon image/bmp application/atom+xml text/javascript application/x-javascript application/pdf application/postscript application/rtf application/vnd.ms-powerpoint application/msword application/vnd.ms-excel application/vnd.wap.xhtml+xml;
  
      fastcgi_cache_path /var/run/cache/nginx levels=1:2 keys_zone=microcache:100m inactive=60m;
      add_header X-Cache $upstream_cache_status;
  
      #limit_req_zone $binary_remote_addr zone=one:10m rate=5r/m;
  
      include /etc/nginx/conf.d/*.conf;
      include /etc/nginx/conf.pre.d/*.conf;
  
  }
  </code></pre>
  
  <p>An example of virtual host will be:</p>
  
  <pre><code>server{
      listen 80;
      server_name   domain.org.dev;
      return        301  https://www.domain.org.dev$request_uri;
  }
  
  server {
          listen   80;
  
          root /var/www/domain;
          index index.html index.htm index index.php;
  
          server_name www.domain.org;
  
          error_page 503 @maintenance;
          location @maintenance {
                  rewrite ^(.*)$ /503.html break;
          }
  
          if ($http_x_forwarded_proto != "https") {
                 rewrite ^(.*)$ https://$server_name$1 permanent;
          }
  
          location / {
                  if (-f $document_root/503.html) {
                      return 503;
                  }
                  try_files $uri/ $uri /index.php?q=$uri&amp;$args;
                  port_in_redirect off;
                  add_header 'Access-Control-Allow-Origin' '*';
          }
  
           location ~ .php$ {
                  #include global/wp-security.conf;
                  include global/php.conf;
                  include global/wp-microcache.conf;
          }
  
          location ~ /.ht(access|passwd) {
                  deny  all;
          }
          location ~ /.git {
                  deny  all;
          }
          location ~ /.svn {
                  deny  all;
          }
          include global/static-content.conf;
  }
  </code></pre>
  
  <p>the most important part is the wp-microcache.conf. Honestly, I took a look on this website to setup my configuration because was very well explained (<a href="https://github.com/A5hleyRich/wordpress-nginx/blob/master/global/server/fastcgi-cache.conf" rel="nofollow noreferrer">https://github.com/A5hleyRich/wordpress-nginx/blob/master/global/server/fastcgi-cache.conf</a>)</p>
  
  <pre><code>fastcgi_cache_key "$scheme$request_method$host$request_uri";
  
  fastcgi_cache_use_stale error timeout invalid_header http_500;
  
  fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
  
  
  set $skip_cache 0;
  
  if ($request_method = POST) {
      set $skip_cache 1;
  }
  
  if ($query_string != "") {
      set $skip_cache 1;
  }
  
  if ($request_uri ~* "/wp-admin/|/wp-json/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
      set $skip_cache 1;
  }
  
  if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
      set $skip_cache 1;
  }
  
  fastcgi_no_cache $skip_cache;
  fastcgi_cache_bypass $skip_cache;
  fastcgi_cache microcache;
  fastcgi_cache_valid 60m;
  </code></pre>
  
  <p>So I ran BlazeMeter test on Wordpress, just GETS so I was expecting pretty success around HITs. However, after analyze results I noticed that many URLS from Worpress were BYPASSING the cache.  Then I understood why I saw so many php-fpm process doing stuff in the EC2 meanwhile test was running.</p>
  
  <p>Anyway, the point is, If I test the Wordpress home (no matter if by curl or navigator):</p>
  
  <pre><code>$ curl -I https://www.domain.org.dev
  HTTP/1.1 200 OK
  Date: Thu, 30 Nov 2017 14:29:19 GMT
  Content-Type: text/html; charset=UTF-8
  Connection: keep-alive
  Server: nginx
  Vary: Accept-Encoding
  Link: &lt;https://www.domain.org.dev/wp-json/&gt;; rel="https://api.w.org/"
  Link: &lt;https://www.domain.org.dev/&gt;; rel=shortlink
  Last-Modified: Thu, 30 Nov 2017 13:53:05 GMT
  Link: &lt;https://www.domain.org.dev/wp-json/&gt;; rel="https://api.w.org/"
  Link: &lt;https://www.domain.org.dev/&gt;; rel=shortlink
  X-Cache: HIT
  </code></pre>
  
  <p>Nevertheless, If I requests other url from the same Wordpress:</p>
  
  <pre><code>$ curl -I https://www.domain.org.dev/about-us
  HTTP/1.1 301 Moved Permanently
  Date: Thu, 30 Nov 2017 14:29:27 GMT
  Content-Type: text/html; charset=UTF-8
  Connection: keep-alive
  Server: nginx
  Last-Modified: Thu, 30 Nov 2017 14:18:58 GMT
  Location: https://www.domain.org.dev/about-us/
  X-Cache: BYPASS
  </code></pre>
  
  <p>Why this different behavior? What things can I inspect in order to fix this? I'm kind of lost here. I suspect there is nothing related with plugins or other stuff.</p>
  
  <p>Any ideas guys?</p>
  
  <p>Thanks!</p>