

 This whitepaper is for historical reference only. Some content might be outdated and some links might not be available.

# Elastic deployment
<a name="elastic-deployment"></a>

 There are many scenarios where a single-server deployment may not be sufficient for your website. In these situations, you need a multi-server, scalable architecture. 

**Topics**
+ [Reference architecture](reference-architecture.md)
+ [Scaling the web tier](scaling-the-web-tier.md)
+ [Stateless web tier](stateless-web-tier.md)

# Reference architecture
<a name="reference-architecture"></a>

 The [Hosting WordPress on AWS reference architecture](https://github.com/awslabs/aws-refarch-wordpress) available on GitHub outlines best practices for deploying WordPress on AWS and includes a set of AWS CloudFormation templates to get you up and running quickly. The following architecture is based on that reference architecture. The rest of this section will review the reasons behind the architectural choices. 

The based AMI in the GitHub was changed from Amazon Linux1 to Amazon Linux2 in July 2021. However, deployment templates at S3 were not changed yet. It is recommended to use templates at GitHub if there is an issue to deploy the reference architecture with templates at S3.

![\[Reference architecture for hosting WordPress on AWS\]](http://docs.aws.amazon.com/whitepapers/latest/best-practices-wordpress/images/image4.png)


* Reference architecture for hosting WordPress on AWS *

**Architecture components**

 The reference architecture illustrates a complete best practice deployment for a WordPress website on AWS. 
+ It starts with edge caching in **Amazon CloudFront **(1) to cache content close to end users for faster****delivery.
+ CloudFront pulls static content from an **S3 bucket** (2) and dynamic content from an **Application Load Balancer** (4) in front of the web instances.
+ The web instances run in an **Auto Scaling group** of **Amazon EC2****instances **(6).
+ An** ElastiCache **cluster (7) caches frequently queried data to****speed up responses.

  An **Amazon Aurora** MySQL instance (8) hosts the WordPress database.
+ The WordPress EC2 instances access shared WordPress data on an **Amazon EFS** file system via an **EFS Mount Target** (9) in each Availability Zone.
+ An **Internet Gateway** (3) enables communication between resources in your VPC and the internet.
+ **NAT Gateways** (5) in each Availability Zone enable EC2 instances in private subnets (App and Data) to access the internet.

 Within the **Amazon VPC** there exist two types of subnets: public (**Public** **Subnet**) and private (**App Subnet** and **Data Subnet**). Resources deployed into the public subnets will receive a public IP address and will be publicly visible on the internet. The **Application Load Balancer** (4) and a Bastion host for administration are deployed here. Resources deployed into the private subnets receive only a private IP address and hence are not publicly visible on the internet, improving the security of those resources. The **WordPress web** **server instances** (6), **ElastiCache cluster instances** (7), **Aurora MySQL database instances** (8), and **EFS Mount Targets** (9) are all deployed in private subnets. 

 The remainder of this section covers each of these considerations in more detail. 

# Scaling the web tier
<a name="scaling-the-web-tier"></a>

 To evolve your single-server architecture into a multi-server, scalable architecture, you must use five key components: 
+ Amazon EC2 instances
+ Amazon Machine Images (AMIs)
+ Load balancers
+ Automatic scaling
+ Health checks

 AWS provides a wide variety of EC2 instance types so you can choose the best server configuration for both performance and cost. Generally speaking, the compute-optimized (for example, C4) instance type may be a good choice for a WordPress web server. You can deploy your instances across multiple Availability Zones within an AWS Region to increase the reliability of the overall architecture. 

 Because you have complete control of your EC2 instance, you can log in with root access to install and configure all of the software components required to run a WordPress website. After you are done, you can save that configuration as an AMI, which you can use to launch new instances with all the customizations that you've made. 

 To distribute end-user requests to multiple web server nodes, you need a load balancing solution. AWS provides this capability through [Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/), a highly available service that distributes traffic to multiple EC2 instances. Because your website is serving content to your users via HTTP or HTTPS, we recommend that you make use of the Application Load Balancer, an application-layer load balancer with content routing and the ability to run multiple WordPress websites on different domains, if required. 

 Elastic Load Balancing supports distribution of requests across multiple Availability Zones within an AWS Region. You can also configure a health check so that the Application Load Balancer automatically stops sending traffic to individual instances that have failed (for example, due to a hardware problem or software crash). AWS recommends using the WordPress admin login page (`/wp-login.php`) for the health check because this page confirms both that the web server is running and that the web server is configured to serve PHP files correctly. 

You may choose to build a custom health check page that checks other dependent resources, such as database and cache resources. For more information, refer to [Health checks for your target groups](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html) in the *Application Load Balancer* *Guide*. 

 Elasticity is a key characteristic of the AWS Cloud. You can launch more compute capacity (for example, web servers) when you need it and run less when you don't. [Amazon EC2 Auto Scaling](https://aws.amazon.com/ec2/autoscaling/) is an AWS service that helps you automate this provisioning to scale your Amazon EC2 capacity up or down according to conditions you define with no need for manual intervention. You can configure Amazon EC2 Auto Scaling so that the number of EC2 instances you’re using increases seamlessly during demand spikes to maintain performance and decreases automatically when traffic diminishes, so as to minimize costs. 

 Elastic Load Balancing also supports dynamic addition and removal of Amazon EC2 hosts from the load-balancing rotation. Elastic Load Balancing itself also dynamically increases and decreases the load-balancing capacity to adjust to traffic demands with no manual intervention. 

# Stateless web tier
<a name="stateless-web-tier"></a>

 To take advantage of multiple web servers in an automatic scaling configuration, your web tier must be stateless. A stateless application is one that needs no knowledge of previous interactions and stores no session information. In the case of WordPress, this means that all end users receive the same response, regardless of which web server processed their request. A stateless application can scale horizontally since any request can be serviced by any of the available compute resources (that is, web server instances). When that capacity is no longer required, any individual resource can be safely terminated (after running tasks have been drained). Those resources do not need to be aware of the presence of their peers – all that is required is a way to distribute the workload to them. 

 When it comes to user session data storage, the WordPress core is completely stateless because it relies on cookies that are stored in the client’s web browser. Session storage isn’t a concern unless you have installed any custom code (for example, a WordPress plugin) that instead relies on native PHP sessions. 

 However, WordPress was originally designed to run on a single server. As a result, it stores some data on the server’s local file system. When running WordPress in a multi-server configuration, this creates a problem because there is inconsistency across web servers. For example, if a user uploads a new image, it is only stored on one of the servers. 

 This demonstrates why we need to improve the default WordPress running configuration to move important data to shared storage. The best practice architecture has a database as a separate layer outside the web server and makes use of shared storage to store user uploads, themes, and plugins. 

# Shared storage (Amazon S3 and Amazon EFS)
<a name="shared-storage-amazon-s3-and-amazon-efs"></a>

 By default, WordPress stores user uploads on the local file system and so isn’t stateless. Therefore, we need to move the WordPress installation and all user customizations (such as configuration, plugins, themes, and user-generated uploads) into a shared data platform to help reduce load on the web servers and to make the web tier stateless. 

 [Amazon Elastic File System](https://aws.amazon.com/efs/details/) (Amazon EFS) provides scalable network file systems for use with EC2 instances. Amazon EFS file systems are distributed across an unconstrained number of storage servers, enabling file systems to grow elastically and allowing massively parallel access from EC2 instances. The distributed design of Amazon EFS avoids the bottlenecks and constraints inherent to traditional file servers. 

 By moving the entire WordPress installation directory onto an EFS file system and mounting it into each of your EC2 instances when they boot, your WordPress site and all its data is automatically stored on a distributed file system that isn’t dependent on any one EC2 instance, making your web tier completely stateless. The benefit of this architecture is that you don’t need to install plugins and themes on each new instance launch, and you can significantly speed up the installation and recovery of WordPress instances. It is also easier to deploy changes to plugins and themes in WordPress, as outlined in the [Deployment Considerations](appendix-a-cloudfront-configuration.md) section of this document. 

 To ensure optimal performance of your website when running from an EFS file system, check the recommended configuration settings for Amazon EFS and OPcache on the [AWS Reference Architecture for WordPress](https://github.com/awslabs/aws-refarch-wordpress#opcache). 

 You also have the option to offload all static assets, such as image, CSS, and JavaScript files, to an S3 bucket with CloudFront caching in front. The mechanism for doing this in a multi-server architecture is exactly the same as for a single-server architecture, as discussed in the [Static Content](accelerating-content-delivery.md) section of this whitepaper. The benefits are the same as in the single-server architecture—you can offload the work associated with serving your static assets to Amazon S3 and CloudFront, thereby allowing your web servers to focus on generating dynamic content only and serve more user requests per web server. 

# Data tier (Amazon Aurora and Amazon ElastiCache)
<a name="data-tier-amazon-aurora-and-amazon-elasticache"></a>

 With the WordPress installation stored on a distributed, scalable, shared network file system, and static assets being served from Amazon S3, you can focus your attention on the remaining stateful component: the database. As with the storage tier, the database should not be reliant on any single server, so it cannot be hosted on one of the web servers. Instead, host the WordPress database on Amazon Aurora. 

 [Amazon Aurora](https://aws.amazon.com/rds/aurora) is a MySQL and PostgreSQL compatible relational database built for the cloud that combines the performance and availability of high-end commercial databases with the simplicity and cost-effectiveness of open source databases. Aurora MySQL increases MySQL performance and availability by tightly integrating the database engine with a purpose-built distributed storage system, backed by SSD. It is fault-tolerant and self-healing, replicates six copies of your data across three Availability Zones, is designed for greater than 99.99% availability, and continuously backs up your data in Amazon S3. Amazon Aurora is designed to automatically detect database crashes and restart without the need for crash recovery or to rebuild the database cache. 

 Amazon Aurora provides a number of [instances types](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html) to suit different application profiles, including memory-optimized and burstable instances. To improve the performance of your database you can select a large instance type to provide more CPU and memory resources. 

 Amazon Aurora automatically handles failover between the primary instance and [Aurora Replicas](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Aurora.Replication.html) so that your applications can resume database operations as quickly as possible without manual administrative intervention. Failover typically takes less than 30 seconds. 

 After you have created at least one Aurora Replica, connect to your primary instance using the cluster endpoint to allow your application to automatically fail over in the event the primary instance fails. You can create up to 15 low-latency read replicas across three Availability Zones. 

 As your database scales, your database cache will also need to scale. As discussed previously in the [Database Caching](database-caching.md) section, ElastiCache has features to scale the cache across multiple nodes in an ElastiCache cluster, and across multiple Availability Zones in a Region for improved availability. As you scale your ElastiCache cluster, ensure that you configure your caching plugin to connect using the configuration endpoint so that WordPress can use new cluster nodes as they are added and stop using old cluster nodes as they are removed. You must also set up your web servers to use the [ElastiCache Cluster Client for PHP](https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/Appendix.PHPAutoDiscoverySetup.html) and update your AMI to store this change. 