The Stack

While every site has its own requirements, all Human Made-hosted sites run a baseline configuration of AWS services and server software. We call all these pieces collectively “the HM stack”.

This page will take you through the common parts of the stack. Each site may have minor variations depending on needs, but generally speaking, you need most of this to run the site.

Infrastructure (AWS services)

The infrastructure is the servers and services managed by the servers team. These pieces are generally solid, although we’re always tweaking this to improve the platform for all our hosting. These changes are then rolled out to our entire fleet.

Elastic Compute Cloud (EC2)

In order to run any software, you need a machine to run it on. This is where Amazon EC2 comes in. EC2 is a virtual private server hosting platform, providing CPU and memory usage of various capacity. These go all the way from 1 virtual CPU with 500MB of RAM, all the way up to 128 CPUs with 2TB of memory.

A single EC2 virtual server is called an instance. Instances exist in an availability zone (AZ), which works similarly to a data centre. AZs are grouped into regions (roughly, city or locality). Regions are named <region>-<area>-<number>, such as eu-west-1 (Ireland) or ap-southeast-2 (Sydney); AZs are identified by a letter (a through c), added to the region name if needed. Each AZ is independent, allowing fault-tolerance; if the power to one AZ is lost, other AZs remain online to handle the traffic.

EC2s replace a traditional hardware web server or VPS. Unlike traditional servers, they can be scaled up dynamically; that is, based on load to the stack, new instances can be provisioned (created) and brought on to handle the traffic demands.

EC2 instances powering the WordPress application are typically called “app servers”.

Elastic Load Balancer (ELB)

In order to accomodate multiple instances, you need a load balancer in front of them. This takes HTTP requests and distributes them to EC2 instances to ensure the load is balanced across all of them. ELBs are the Amazon solution to this.

ELBs distribute requests based on a round-robin system to EC2 instances, and works in a region across zones; that is, an eu-west-1 ELB can distribute requests to instances in eu-west-1a or eu-west-1b equally.

ELBs control scaling and availability. If the ELB detects that EC2 instances are failing, it will remove them from the pool of valid instances, and will mark the instance as failed. If the ELB is controlling autoscaling, it will shutdown and deprovision the instance, then replace it with a new instance. Similiarly, if the ELB detects that the site is under heavy load and is unable to cope with the traffic, it can provision new EC2 instances and add them to the pool to accomodate.


A level above the ELB is CloudFront, a cache and CDN. Unlike most other AWS services, CloudFront is global, providing users with cached content at their closest edge node.

CloudFront is both a full-page cache and static asset cache, with differing rules for each. Uploads are transparently passed through to S3 requests, and are cached for a year.

CloudFront automatically uses caching headers generated by WordPress, and works well with Batcache if installed on a site. It is set up to pass-through authenticated requests (any cookie prefixed with wordpress_, wp_, wp- or hm_). CloudFront only caches GET requests to allow passing write requests through to WordPress.

SSL connections are typically terminated at the CloudFront server.

Relational Database Service (RDS)

To power WordPress, you need MySQL. While you can run this yourself on a machine easily, it has its own scaling characteristics. RDS is a hosted database (such as MySQL) that handles scaling, reliability, availability, and security for you.

Typically, we use RDS as a hosted MySQL server, however other database types (including Amazon Aurora, a MySQL-compatible database) are available.

Similar to EC2s, RDS has instances with pricing based on the size required.


To avoid hitting the database on every request, a persistent object cache is used. WordPress supports many of these through plugins; we use Memcache, powered by ElastiCache.

This is used as WordPress’ persistent object cache, and can be used as the storage for full-page caching solutions like Batcache.

ElastiCache is priced similarly to RDS.

Simple Storage Service (S3)

With multiple servers, files need to be shared across instances. In WordPress, user-writable content is stored in the uploads directory under the site’s content directory. We swap this out for S3 storage instead, using the S3 Uploads plugin.

S3 is also used for storing backups and other forms of dynamically-generated binary data.

Server logs are also saved to S3, then pushed to Loggly for later viewing and management. These logs are pushed to Loggly by a Lambda function, triggered when the server log is written.


Lambda is a serverless platform, allowing applications written in Node.js, Python, and Java to run without requiring servers to be set up beforehand. Instead, Lambda runs the code only when it’s needed.

We use Lambda to power Tachyon, our scalable image serving and resizing service. Tachyon reads uploaded images directly from S3, and serves them to the end-user via CloudFront. CloudFront caches these images.

Simple Email Service (SES)

Our EC2 instances don’t have built-in mail sending services, but instead use Amazon SES instead. This allows high volume email with high deliverability rates.

Using SES requires the SES plugin to be active. Alternative choices such as Mandrill can also be used as necessary.


CloudFormation is the tool that manages all the pieces and ties them together into a stack. This is typically used by the servers team directly, using a “template” that specifies exactly how to build a new stack.

CloudFormation is also responsible for the creation of some of the stack-wide pieces, including the security group, which allows the services to access each other without exposing themselves to the outside world.

Server Software


Every server we have runs nginx. nginx is used purely as a lightweight HTTP server, passing requests through to PHP via php-fpm.

nginx caching is not enabled for our stack; we instead use caching at a higher level with CloudFront, or at a lower level with Batcache.

PHP (5.4 through 7.0)

In order to run WordPress, you need PHP. We’re running PHP 7 for all our newer stacks, and older stacks are being progressively updated to use this.


Cavalcade runs as a daemon (system service) on every server, but remains inactive unless the site has also installed the Cavalcade plugin.

We run Cavalcade through Upstart, a Ubuntu utility for managing daemons.