Skip to content

Classic Solutions Architecture

The deck calls this section the best part of the course, and it is not being modest: everything covered so far — EC2, security groups, EBS, EFS, ELB, Auto Scaling Groups, RDS, Aurora, ElastiCache, Route 53 — finally gets used together. This is a section to be 100% comfortable with, because the exam is mostly scenario questions and scenario questions are exactly this shape.

The chapter follows the progression of a solutions architect’s thinking through a series of case studies:

  • WhatIsTheTime.com — a stateless web app.
  • MyClothes.com — a stateful web app with a shopping cart.
  • MyWordPress.com — a stateful web app with file uploads.
  • Instantiating applications quickly.
  • Elastic Beanstalk.

The point of each is not the final diagram but the sequence of problems that forces each new component into the design.

2. Case study 1 — WhatIsTheTime.com (stateless)

Section titled “2. Case study 1 — WhatIsTheTime.com (stateless)”

The requirements: the site tells people what time it is, so no database is needed. We want to start small and can accept downtime initially, but we want to be able to scale fully, vertically and horizontally, with no downtime later.

One public EC2 instance with an Elastic IP. A user asks what time it is, the instance answers. Cheap, trivially understood, and a single point of failure.

Traffic grows, so we move to a bigger instance — say an M5. Because vertical scaling means changing the size of that one instance, there is downtime while upgrading. The Elastic IP means the address does not change, which is the only reason this is tolerable at all.

Instead of one big instance we run several. Now the Elastic IP model breaks down: you cannot hand every user a different address. The answer is DNS: create an A record for api.whatisthetime.com with several public EC2 instances behind it, and let clients resolve the name. The deck’s version uses a TTL of 1 hour.

The DNS-only approach fails as soon as instances come and go. A record still advertises an instance that is gone, and because the record was cached with a one-hour TTL, clients keep trying to reach it for up to an hour. There is no health checking and no way to remove a dead instance quickly.

So we insert an ELB with health checks in front of the instances, and the DNS record for api.whatisthetime.com becomes an Alias record pointing at the load balancer. The instances become private, with restricted security group rules so they only accept traffic from the load balancer’s security group. A dead instance now fails its health check and is pulled out of rotation, and no client ever sees its address.

Managing the instance count by hand is the next thing to go. An Auto Scaling group behind the ELB adds and removes instances with load and replaces failed ones automatically.

Everything so far still lives in one Availability Zone. Spreading the ELB and the Auto Scaling group across AZs 1 to 3 turns the design into a genuinely highly available one: losing an AZ costs capacity, not the service.

Since a multi-AZ ASG has a minimum of 2 AZs and therefore a permanent baseline of instances that never goes away, that baseline can be bought as reserved instances — the minimum capacity equals reserved instances equals cost savings. Only the elastic portion above the minimum needs to be on-demand.

The ground covered: how public and private addressing works on EC2 instances, and where an Elastic IP stops being enough and Route 53 or a load balancer takes over; what a Route 53 TTL does, and the difference between an A record and an Alias record; the gap between tending instances by hand and handing them to an Auto Scaling group; spreading over several AZs so that a disaster does not take the service with it; the health checks the ELB performs; the rules written into the security groups; and the baseline capacity you can reserve for a cheaper bill when the workload allows it.

3. Case study 2 — MyClothes.com (stateful)

Section titled “3. Case study 2 — MyClothes.com (stateful)”

The requirements: people buy clothes online, so there is a shopping cart. The site has hundreds of concurrent users. We must scale horizontally and keep the web tier as stateless as possible, users must not lose their shopping cart, and user details such as addresses must live in a database.

The starting point is where case study 1 ended: an ELB in front of a multi-AZ Auto Scaling group across three AZs. The new problem is the cart.

Turn on ELB stickiness (session affinity) so a user always returns to the same instance, and the cart can live in that instance’s memory. It works, but it is fragile: if that instance is terminated by a scale-in event or a failure, that user’s cart is gone.

Send the shopping cart contents to the client in web cookies. The web tier becomes genuinely stateless, which is what we wanted. The costs are real, though:

  • HTTP requests get heavier, since the whole cart travels with every request.
  • It is a security risk — cookies can be altered by the client.
  • Cookies must be validated server-side before they are trusted.
  • Cookies must be less than 4 KB.

The better answer. Send only a session_id in a web cookie and keep the session data itself in ElastiCache, which any instance can read and write. The web tier stays stateless, the cart survives any individual instance dying, and requests stay small. Amazon DynamoDB is the alternative store for the same pattern.

Longer-lived user data — name, address and so on — goes into Amazon RDS, which the instances read from and write to.

Two options, and they are not exclusive:

  • RDS read replicas: the master takes the writes, replicas serve the reads, replication flows from master to replicas.
  • Lazy loading through ElastiCache: the application reads from the cache first; on a hit it never touches RDS, and on a miss it reads from RDS and writes the result into the cache.

Both data stores get their own multi-AZ treatment: RDS Multi-AZ and ElastiCache Multi-AZ, on top of the ASG already spanning three AZs.

The tightest configuration chains the security groups together, each layer referencing the one in front of it rather than an IP range:

Layer Rule
Load balancer Open HTTP / HTTPS to 0.0.0.0/0
EC2 Restrict traffic to the EC2 security group from the load balancer’s security group
RDS Restrict traffic to the RDS security group from the EC2 security group
ElastiCache Restrict traffic to the ElastiCache security group from the EC2 security group

This one assembled a 3-tier architecture for a web application, and with it: sticky sessions on the ELB; cookies held by the web client as a way of taking state out of the application; ElastiCache in two distinct roles — the session store, where DynamoDB would serve just as well, and a cache in front of RDS — running multi-AZ; RDS as the home of user data, with read replicas absorbing the reads and Multi-AZ covering disaster recovery; and a tight security posture in which each security group names the one in front of it.

The requirements: a fully scalable WordPress website, that can accept and correctly display picture uploads, with user data and blog content stored in a MySQL database.

Start with RDS Multi-AZ behind the multi-AZ Auto Scaling group. Scaling it further, the deck moves to Aurora MySQL, which brings easy Multi-AZ and read replicas in one managed cluster.

An uploaded image written to an EBS volume attached to the instance that received it is fine while there is exactly one instance. Add a second instance in another AZ and the problem is immediate: that instance has its own EBS volume, does not have the image, and a user routed to it sees a broken picture. EBS volumes are attached to a single instance in a single AZ, so they cannot back a distributed web tier.

EFS solves it. The file system is shared, and each AZ’s instances reach it through an ENI (a mount target). Every instance in every AZ sees the same uploaded files, so it does not matter which one handled the upload or which one serves the page.

Aurora as the way to get Multi-AZ and read replicas with little effort, and the split between EBS, which fits an application living on a single instance, and EFS, which is what a distributed one needs.

Launching a full stack of EC2, EBS and RDS takes time: you have to install applications, insert initial or recovery data, configure everything and then start the application. The cloud lets you shortcut most of that:

  • EC2 instances
    • Use a Golden AMI: install the applications and OS dependencies beforehand and launch instances from that AMI.
    • Bootstrap using User Data: run a script at boot for whatever configuration has to be dynamic.
    • Hybrid: combine a golden AMI with user data — this is what Elastic Beanstalk does.
  • RDS databases
    • Restore from a snapshot: the database comes up with its schemas and data already in place.
  • EBS volumes
    • Restore from a snapshot: the disk is already formatted and already contains the data.

6. The typical 3-tier web app architecture

Section titled “6. The typical 3-tier web app architecture”

Putting the pieces in their subnets gives the canonical layout:

Tier Subnet What lives there
Presentation Public subnet Route 53 resolving to the ELB
Application Private subnet The Auto Scaling group of EC2 instances, spread across availability zones 1 to 3, multi-AZ
Data Data subnet ElastiCache for session data and cached data, and Amazon RDS for reading and writing the durable data

The web tier is reachable from the internet; the application tier is not, and is reached only through the load balancer; the data tier is reached only from the application tier.

Developers on AWS face the same set of chores on every project: managing infrastructure, deploying code, configuring the databases and load balancers, and worrying about scaling. Meanwhile most web applications have the same architecture anyway — an ALB plus an ASG. All the developers actually want is for their code to run, ideally the same way across different applications and environments.

Elastic Beanstalk is a developer-centric view of deploying an application on AWS. It uses the components already covered — EC2, ASG, ELB, RDS — and manages them for you:

  • Capacity provisioning, load balancing, scaling, application health monitoring and instance configuration all happen without you arranging them.
  • What is left on the developer’s plate is the application code, and nothing else.
  • The configuration remains entirely yours to control when you want to reach into it.
  • The service itself costs nothing; the bill is for the instances underneath.
Component Meaning
Application A collection of Elastic Beanstalk components — environments, versions, configurations
Application version One iteration of your application code
Environment A collection of AWS resources running one application version at a time; you can create several environments such as dev, test and prod

Environments come in two tiers: the Web Server Environment Tier and the Worker Environment Tier.

The workflow is: create an application, upload a version, launch an environment, then manage the environment — updating the version and deploying new versions from there.

Go · Java SE · Java with Tomcat · .NET Core on Linux · .NET on Windows Server · Node.js · PHP · Python · Ruby · Packer Builder · Single Container Docker · Multi-container Docker · Preconfigured Docker.

A Web Server environment is what you expect: an ELB in front of an Auto Scaling group of EC2 web servers spread over two Availability Zones, with security groups, reachable at a hostname like myapp.us-east-1.elasticbeanstalk.com.

A Worker environment has no load balancer. Its Auto Scaling group of worker instances pulls messages from an SQS queue, and it scales on the number of SQS messages. Messages can be pushed to the queue by a Web Server tier, which is the standard way to split a slow background job out of the request path.

  • Single Instance — one EC2 instance with an Elastic IP and an RDS master. Great for dev.
  • High Availability with Load Balancer — an ALB in front of an Auto Scaling group spanning two AZs, with an RDS master and standby. Great for prod.
Topic What to remember for the exam
WhatIsTheTime.com Stateless, no database; Elastic IP does not scale horizontally, plain DNS has no health checking and stale TTLs, so the answer is Route 53 Alias to an ELB plus an ASG, multi-AZ
Instances behind a load balancer Make them private and let the security group accept traffic only from the load balancer’s security group
Reserved capacity The ASG’s minimum capacity is permanent, so it is the part worth buying as reserved instances
Keeping sessions ELB stickiness loses data when an instance dies · cookies are stateless but heavy, alterable and limited to 4 KB · session_id cookie plus ElastiCache (or DynamoDB) is the right answer
Scaling reads RDS read replicas, or ElastiCache lazy loading in front of RDS
Disaster recovery in the data tier RDS Multi-AZ and ElastiCache Multi-AZ
Security group chaining LB open to 0.0.0.0/0 · EC2 from the LB’s SG · RDS and ElastiCache from the EC2 SG
MyWordPress.com storage EBS = single instance, EFS = distributed application — shared uploads across AZs need EFS with an ENI per AZ
Fast instantiation Golden AMI, User Data bootstrap, or a hybrid of both; RDS and EBS restore from snapshot
3-tier layout Public subnet Route 53 and ELB · private subnet ASG of EC2 · data subnet ElastiCache and RDS
Elastic Beanstalk Developer-centric managed deployment over EC2/ASG/ELB/RDS; free, you pay for the instances; you keep full configuration control
Beanstalk components Application · application version · environment (one version at a time, tiers: Web Server and Worker)
Worker tier No load balancer; pulls from an SQS queue and scales on the number of messages
Deployment modes Single Instance for dev · High Availability with Load Balancer for prod