How to best load balance a WordPress/WooCommerce e-commerce site?

Posted February 21, 2018 25.8k views
WordPressSecurityLoad BalancingUbuntu 16.04

I have been running my WordPress/WooCommerce e-commerce and membership site happily for a couple of years now all on one server. But my traffic and membership is such that I want to transition to a more fault tolerant setup. I was thinking of the following:

  • 1 DB server
  • 2 WordPress servers (setup using easyengine with NGINX, PHP7)
  • 1 Load Balancer

The above setup should be all I need for now, but I have a few questions:

  1. SSL passthrough to each of the WP servers or not? What happens when someone makes a purchase if SSL is terminated on the Load Balancer? Does this all just work seamlessly with (or other gateways) or are there some issues there?

  2. Are there specific nginx config or session gotchas in this scenario?

  3. What about server naming? What are the server names in each of the WP servers if they are sharing the same DB? how do I make them different? DO i need to make them different?

  4. Anything else I should be aware of?


These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Submit an Answer
2 answers

Well, in case anyone was interested, here is what I ended up doing:

After reading up on GlusterFS, I had a ton of reservations about performance issues for my needs. In short, it is apparently horrible for the multiple small files scenario that my wordpress sites represent, and much better suited to medium to large media files. So instead, I set up lsyncd from wp1 to wp2, and although it is a few seconds delay to copy/sync, it is more than adequate for my needs.

For setting up the load balancer:

  1. I first pointed my domain to wp1 IP
  2. I then generated a letsencrypt (cert only) so that I would have the cert info I needed.
  3. Then I added this info manually from the files certbot generated to the load balancer
  4. Then I pointed my domain to the load balancer, force all traffic to SSL, and connect to port 80 of my droplets behind the load balancer

For naming my wordpress servers:

  1. I called one of them and the other
  2. I manually added entries in the otherwise identical wp-config.php file on each server with the following: define('WP_HOME',''); define('WP_SITEURL','');
  3. I exclude wp-config.php from my lsyncd setup btw, and sync everything else in /var/www/html

For the DB, both wp1 and wp2 point to the same (third) server ( and serve the identical info.

The only issue may be having to clear the cache manually from time to time on each server individually, but I am looking into creating a button/plugin in the wp admin that will clear both servers’ nginx cache at the same time/on the same click. Other than that, I am super happy with the setup! Anyone have any thoughts or critiques of this approach?

  • I need to add a very important change that I needed here. If I wanted to use permalinks, this completely BROKE the load balancer with the above setup. I had to do the following:

    1. Change wp-config on both sites to use: define('WP_SITEURL', 'https://' . $_SERVER['HTTP_HOST']); define('WP_HOME', 'https://' . $_SERVER['HTTP_HOST']);
    2. Change nginx config to include both the address of my load balancer as well as my wp1 and wp2 addresses.
    • Did you happen to encounter problems when trying to do Appearance -> Customize where you get the error “Non-existent changeset UUID” and if so how did you resolve this?

    • Do you mind sharing your exact setting (Change the private info, of course)for both of the servers? I can’t seem to make it works. I have individual wp with nginx working and the LB with Nginx as is working but the second I added the LB in, I got the “The page isn’t redirecting properly”. The part I’m confused of is the Site URL and home URL part. I can go directly to the DB to put the WP Client as the address and LB IP or subdomain but then if you have 3 WP clients, where am I supposed to put the rest? I’m confused and so frustrated.

  • Would you be able to post your lsyncd script?

This is a great place to start for a scalable WP installation.

A few caveats I have run into / answers to a couple questions

A note DO does setup PTR records for droplets with names that resolve to their IP address - for example - add a sub-domain for that points to the droplet. Something to take into consideration.

Each of your WordPress/Application(s) can access the same DB Server. However in higher traffic situations your DB will become taxed. You could add a Redis Cache Server to your setup to help with this or use use something like the WordPress Plugin HyperDB to spread the database across multiple nodes, or setup a DB cluster - a few choices or combination of choices here.
A start -

Moving ahead to a more fault tolerant architecture you might want to look at this for your load balancer

Another caveat I ran into is keeping each application/wordpress installation in sync with each with assets, plugin/theme versions etc…

The asset(s) aspect could be solved by moving this into DO Spaces - There are many WP Plugins available to help link the space and your media folder up.

As for the application server(s) being in sync, you could move your WP installation into a docker container and store the files on a shared network volume.

Hope this helps

by Ryan Quinn
Create and deploy a scalable WordPress instance consisting of a MySQL database server, a GlusterFS distributed filesystem, Nginx web servers and an Nginx load balancer. By using user-data and droplet meta-data we will automate the deployment of our site.
  • Thanks for the great advice. Still not sure I am understanding the naming of the servers underneath the load balancer though…how do I make sure that even though my users are accessing (which gets load balanced between the two web servers) I have a way to to access the wordpress interface of and separately? How does the load balancer present each wp admin installation if they are named differently? And if they are sharing the db, don’t they need to have the same site url in the options table?

    Or should I just forget about all of this and just go with a Gluster FS as indicated in one of your links? I assume that way each web server is just serving a shared identical filesystem…