Building Infrastructure to Serve Millions of Users on AWS: 1K Users

Quân Huỳnh
7 min readMay 18, 2024

--

In the previous article, we built a simple infrastructure to serve hundreds of users. In this article, we will learn how to expand that simple infrastructure to serve thousands or even tens of thousands of users.

The series includes:

  • Lesson 0: Install WordPress on EC2 and create RDS + S3
  • Lesson 1 — 1k users: package EC2 and set up a load balancer and autoscaling group
  • Lesson 2 — 10k users: create database replica, connect master — replica
  • Lesson 3 — 100k users: implement cache system by creating Elasticache
  • Lesson 4 — More than 500k users: implement HTTP cache system

The infrastructure we created in the previous article.

It will be expanded next to serve thousands of users, as illustrated below.

The infrastructure includes:

  • AWS Application Load Balancer
  • Auto-Scaling Group
  • AWS RDS
  • AWS S3

Infrastructure for scale

Regarding scaling, we have two methods: Vertical Scaling and Horizontal Scaling. We will not go into depth about the theory, but we can define Vertical Scaling and Horizontal Scaling as follows:

  • Vertical Scaling: Scale by adding power to a workload (server or database) in the system, for example, by increasing CPU or memory.
  • Horizontal Scaling: Scale by adding more the number of workloads in the system, for example, by doubling the number of servers.

Apps that hold data (stateful) should use vertical scaling, whereas stateless apps should use horizontal scaling. Our WordPress application is stateless because it uses RDS to store data and S3 Bucket to store pictures instead of having its own data storage. We will use the Horizontal Scaling method to expand EC2 WordPress to serve thousands of users.

Initially, we only had one EC2 WordPress instance, and everything was fine when our users were in the hundreds.

However, one EC2 will not be able to support thousands of users, thus we will need to add more EC2s to grow.

Here’s how the horizontal scaling approach is put into practice. This will be a little more challenging to accomplish if the system is being operated on-premises, but with Auto Scaling Group on AWS, it is fairly straightforward. To create an Auto Scaling Group, we will need the following:

  • Amazon Machine Images (AMI)
  • AWS Launch Template
  • Auto Scaling Group

Amazon Machine Images (AMI)

The AMI will help us package an EC2 instance into an image (similar to how we package an application into a container image). The AMI will contain everything from the EC2 instance we have packaged, and we just need to create a new EC2 instance from that AMI.

For example, in this article, we will package our EC2 instance running WordPress into an AMI. Then, we just need to create a new EC2 instance from that AMI, and it will have everything we need. This is a resource that makes it easier for us to expand our system. Accessing the AWS EC2 Console, we will see that there is an EC2 instance; we will proceed to package it into an AMI.

  • Select the EC2 instance running WordPress
  • Select the Action Menu
  • Choose Image and templates -> Create image
  • Enter the image name
  • Click on Create image

In the menu, click on Images -> AMIs, and you will see the AMI you just created.

EC2 Launch Templates

The next step is to create Launch Templates for the Autoscaling Group.

  1. Go to AWS EC2 Console
  2. Select Instances -> Launch Templates
  3. Click Create launch template
  4. Enter a name for the template
  5. In the Launch template contents -> Application and OS Images (Amazon Machine Image) section, select My AMIs -> Owned by me and search for the AMI named WordPress that was created earlier
  6. In the Instance type section, select t3.small
  7. In the Key pair (login) section, select the key you created
  8. In the Security Groups section, click Create security group
  9. Click Create

EC2 Auto Scaling Group

Finally, we create an ASG from the Launch Templates above. The entire EC2 instance created from this ASG is the same as our original EC2 WordPress, with everything available from WordPress configuration, connection configuration to the Database, and connection configuration to S3. Follow these steps:

  1. Go to the AWS EC2 Console
  2. Select Auto Scaling -> Auto Scaling Groups
  3. Click Create Auto Scaling group
  4. In the Auto Scaling group name section, enter a name for the group
  5. In the Launch template section, select the Launch Template we created for WordPress
  6. In the VPC section, select Default, and in the Availability Zones and subnets section, select all
  7. In the Load balancing section, select No load balancer
  8. Set Desired capacity = 1, Minimum capacity = 1, Maximum capacity = 4. In the Group size section, enter Scaling policies, select Target tracking scaling policy

Here we are configuring that when the current number of EC2 instances runs more than 50% CPU, the ASG will automatically create new EC2 instances. Click Skip to review, and Create Auto Scaling group.

Go to the AWS EC2 Console, and you will see that there are now 2 EC2 instances. Click on the new one and paste its address into the browser. We will see WordPress displayed like the old one; we have succeeded. You should add your old instance to the ASG so that the ASG can manage it.

We now have several WordPress EC2 instances, and every one of them has a unique IP address. Here’s where the issue arises: how are our users supposed to know which one they need to access?

We use AWS Application Load Balancer to solve this problem.

AWS Application Load Balancer

Requests from users will be received by the AWS Application Load Balancer, which will then route them to each EC2 WordPress instance.

Using an Application Load Balancer (ALB) is a very common architecture pattern in system design. Let’s create an ALB in AWS by following these steps:

  • Go to the AWS EC2 Console
  • Select Auto Scaling -> Auto Scaling Groups and find the ASG we just created
  • Scroll down to the Load balancing section and click the Edit button
  • Click Add a new load balancer
  • In the Load balancer type section, select Application Load Balancer
  • In the Load balancer scheme section, select Internet-facing
  • In the Listeners and routing -> Default routing (forward to) section, click Create a target group

We have now successfully created an AWS Application Load Balancer (ALB). To see the URL of the ALB:

  1. Go back to the AWS EC2 Console
  2. Select Load Balancing -> Load Balancers

The DNS name section contains the URL of the ALB. Instead of accessing the EC2’s IP address, we will now access the ALB’s URL. Simply paste the ALB’s address into your browser, and you will see the WordPress page. For example, mine is http://wordpress-1-835238640.ap-southeast-1.elb.amazonaws.com/.

However, accessing the admin page may not work initially because the WordPress Root URL configuration in the Database. To resolve this, you can access the Database and make the necessary edits. For example, using a tool like Navicat, access the table wp_options and edit the values of the two rows: siteurl and home.

We may now access the admin page.

Conclusion

We have learned how to expand the infrastructure architecture to serve thousands of users. This architecture includes an Application Load Balancer (ALB), Auto Scaling Group (ASG), and Database. This is a very popular and scalable architecture pattern in system design.

In the next article, we will build upon this basic infrastructure architecture and expand it further to serve tens of thousands of users.

--

--

Quân Huỳnh

I’m a technical blogger and love writing. I write about Kubernetes, AWS Cloud, and Terraform.