Categories
Azure Windows

Making WordPress fast(er) on Azure App Service

I noticed that WordPress and WordPress Multisite on Azure does not perform well. It seems that anything written in PHP is not the first class citizen on Azure and PHP runtime as well as MySQL behaves differenly on Azure than running it on VM or Docker.

I was not able to make WordPress as fast as it would be on VM but I got close. Please notice that I am running App Service under Windows Operating System. If you have change to run this under Linux you will likely get much better performance and some of the tips below may not be relevent for you. In any case fine tuning these settings are always solution specific but if you have performance problems I hope my findings helps you.

Step 0 – App and SQL plans

App Service
You should run the App Service in minimum P1V2. Everything smaller in a bigger solution becomes slower. This gives 210 total ACU 3.5 GB memory for the app.

Azure Database for MySQL server

Gen 5 with 100 GB and 4 cores seemed to work for me. I noticed that there was not much of difference if you choose Basic with 2 vCores. If you don’t need large storage I recommend trying out Basic first but notice that you cannot scale from Basic to General Purpose with a click of a button. It requires moving db’s manually.

Step 1 – App Service Settings

Changes Made: 

  • PHP version 7.4
  • Set the Platform as 64 bit
  • Set HTTP-version to 2.0
  • Set the site to ‘Always on
  • Turn Off the Affinity Cookie

Step 2 – Extend PHP.INI

Open the solution in Kudu or FTP client and create new folder at d:\home\site\ini on your app structure. Under new ini -folder create settings.ini and add following settings:

wincache.maxfilesize=1024M
memory_limit=2048M
upload_max_filesize=50M
post_max_size=50M
max_execution_time=3600
max_input_time=300
output_buffering = Off;

wincache.maxfilesize
– Defines the maximum allowed size (in kilobytes) for a single file to be cached.

memory_limit=2048M
– This sets the maximum amount of memory in bytes that a script is allowed to allocate.

upload_max_filesize, post_max_size, max_execution_time, max_input_time
– You may not need this. I got some bigger file execution operations in relation to a WP plugin that required extend size and execution times. Not exactly related to performance.

output_buffering
– I don’t really understand why this is set on Azure. App seems to run better if it is disabled?

After adding the settings.ini under d:\home\site\ini\ folder open App Service > Configuration > Application Settings and the folder to the key called PHP_INI_SCAN_DIR=d:\home\site\ini\ like this:

Save and restart the App Service. Now you should have custom INI for your app where you can adjust default PHP settings.

You can verify that your settings are correct by creating phpinfotest.php with <?php phpinfo(); ?> in it and uploading it to the webroot. Then on your browser you can see this file and see all your settings.

Redis Object Cache and App Service Local Caching

I have tried both of these and neither them helped me but it might help on some installations. So I will write few words about them

App Service Local Caching

The Azure App Service Local Cache feature provides a web role view of your content. This content is a write-but-discard cache of your storage content that is created asynchronously on-site startup. When the cache is ready, the site is switched to run against the cached content. Enabling local caching will change how the storage works for your app service. This is only recommended for more static WordPress instances and not for WordPress instances that have new posts or pages.

To enable it add these settings to your application settings

WEBSITE_LOCAL_CACHE_OPTION Always
WEBSITE_LOCAL_CACHE_SIZEINMB 2000

I have heard and read this is great setting on some solutions but for me performance got 10 x worse with local caching. So I drop it.

Redis Object Cache

Object caching allows your web application to cache the results of queries as objects in low latency memory based storage. But this is also something that may not work for your solution. I did not have good luck on my solution, on my instance speed got 10-15% slower after enabling Redis. There are a few caveats to using the Redis Object Cache approach on WordPress. The caching mechanism does not work well if you have a lot of plugins and themes installed. This is due to the fact that all their data would need to be cached as well with Redis. But it is worth of testing since Azure Cache for Redis is easy to setup and test it. If you don’t see benefits on it you can just delete it. I followed this blog post to configure caching with Redis.

If you have a lot of visitor on the site I think you should definetly evaluate Redis.

Cache Plugins for WordPress

I tested different cache plugins that work with WordPress Multisite and I settled with WP Super Cache. This plugin is simple and quick to configure. If you install the plugin and just enable it it works. Only custom setting I added was in the advanced section I extended cache recycling to 1 hour.

Azure Content Delivery Network (CDN)

Azure Content Delivery Network (CDN) lets you reduce load times, save bandwidth and speed responsiveness. You can use the same cache plugin WP Super Cache to enable CDN.

Other tips

A few tips to improve WordPress performance and overall settings on Azure Web App are listed below:

  <requestFiltering>
    <denyUrlSequences>
      <add sequence="xmlrpc.php" />
    </denyUrlSequences>
  </requestFiltering>
  • Add .woff mimetypes
    <staticContent>
      <mimeMap fileExtension="woff" mimeType="application/font-woff" />
      <mimeMap fileExtension="woff2" mimeType="application/font-woff2" /> 
        <remove fileExtension=".mp4" />
        <mimeMap fileExtension=".mp4" mimeType="video/mp4" />
        <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
     
    </staticContent>

Summary

It is possible to get decent performance on WordPress solutions on App Service but I am still in doubt if this is the better solution than running on Virtual Machine or in the container. I never was able to get close to performance that I can get on Virtual Machine with dedicated application server and MySQL server under Linux. Although, Azure is getting better and faster everyday and there is no doubt that eventually it will be at least as fast as VM.