Three-tier reference architecture
The three-tier web app, done properly
ALB, Auto Scaling across AZs, RDS Multi-AZ, and CloudFront on top, because half the associate exam is this one diagram and the places it can fall over.
Why this shape keeps showing up
The Well-Architected reliability pillar opens with the observation that reliability is hard on premises for three specific reasons: single points of failure, lack of automation, and lack of elasticity. The three-tier reference architecture is AWS's standing answer to all three, which is why some version of it sits behind an enormous share of SAA-C03 questions. Presentation tier at the edge, application tier on load-balanced compute, data tier on a managed relational database. Each tier gets its own redundancy mechanism, and the seams between tiers are where exam questions live.
The unit of failure the whole design is built around is the Availability Zone. Every stateful and stateless layer is deployed across at least two AZs, and each layer has a different mechanism for surviving the loss of one. The Application Load Balancer distributes traffic across targets in multiple AZs and routes only to targets that pass health checks. The Auto Scaling group monitors instance health, replaces impaired instances to maintain desired capacity, and balances instances evenly across the AZs you give it. RDS Multi-AZ maintains a synchronous standby replica in a different AZ and fails over to it automatically.
Notice what each mechanism does NOT do. The ALB does not create new capacity; it only steers traffic away from unhealthy targets. The Auto Scaling group does not route traffic; it only maintains the fleet. The RDS standby does not serve any traffic at all until failover promotes it. Exam distractors routinely swap these responsibilities, so keep the division of labor sharp: ALB routes, ASG replaces and scales, Multi-AZ standby waits.
A request walks through
Follow one browser request end to end. First, DNS: Route 53 resolves the site's domain to the CloudFront distribution. CloudFront routes the request to the edge location with the lowest latency for that viewer. If the request is for a static object (CSS, JS, images) and the edge has it cached, the response never touches your VPC at all. On a miss, CloudFront fetches from the origin you configured for that path, typically an S3 bucket for static assets, caches it at the edge (24 hours by default, tunable from zero with no maximum), and serves it. This is the quiet workhorse of the design: the static tier absorbs most of the request volume so the expensive tiers only see dynamic traffic.
Dynamic requests get forwarded to a second origin, the internet-facing ALB in the public subnets. The ALB evaluates its listener rules in priority order and picks a target from the matched target group, round robin by default, or least outstanding requests if you configure it. Health checks are defined per target group, and only healthy targets receive traffic. The targets are EC2 instances in an Auto Scaling group spread across private subnets in two AZs. The integration between the two services is automatic and bidirectional: instances the ASG launches are registered with the target group, and instances it terminates are deregistered. When CloudWatch metrics breach a scaling policy threshold, the group launches or terminates instances between its min and max, keeping the fleet balanced across AZs as it grows and shrinks.
The app instance then talks to the data tier: an RDS Multi-AZ DB instance reached through a single DNS endpoint. Every write commits synchronously to both the primary and the standby replica in the other AZ, which is what makes failover lossless, and also why Multi-AZ deployments can show higher write and commit latency than Single-AZ. When the primary becomes unhealthy (impaired host, storage failure, network partition, an OS patch during the maintenance window, or a manual reboot-with-failover), RDS promotes the standby and repoints the instance's DNS record at it. Typical failover takes 60 to 120 seconds, and the application's only job is to reconnect: same endpoint name, new address underneath. That last step is a classic trap. A JVM that caches DNS lookups indefinitely will keep hammering the dead primary's IP forever, which is why AWS documents setting networkaddress.cache.ttl to 60 seconds or less.
What this teaches for the exam
For task 2.2 (highly available and fault-tolerant architectures), this pattern is the canonical answer to 'mitigate single points of failure.' Audit the diagram like the exam does: an ASG confined to one AZ, an ALB with all its instances in one subnet, or a Single-AZ RDS instance under a multi-AZ app tier are all availability bugs the correct answer fixes. Know the RDS Multi-AZ facts cold: synchronous replication, automatic failover in roughly 60 to 120 seconds via a DNS flip, failover triggered by host, storage, or network failure as well as planned OS maintenance, and no application code changes required beyond reconnecting. Just as important, know its limits: a Multi-AZ single-standby deployment is a high-availability feature, not a scaling feature, and the standby cannot serve reads. When a question wants read scaling, the answer is read replicas or a Multi-AZ DB cluster, not the standby.
For task 3.2 (high-performing and elastic compute), the ALB plus ASG pairing is the reference implementation of 'identify metrics and conditions to perform scaling actions.' Min, max, and desired capacity bound the fleet; scaling policies move desired capacity in response to demand; health checks (EC2 status checks, plus ELB health checks or custom checks when the app can fail while the OS stays healthy) trigger replacement rather than scaling. Offloading static content to CloudFront and S3 is itself an elasticity answer: it removes load from the compute tier entirely, which usually beats adding instances on both performance and cost.
Finally, use the pattern as a baseline for spotting what a question is really asking. If the scenario adds 'users lose their carts when an instance terminates,' the defect is state on instances and the fix is externalizing session state, not more AZs. If it says 'reads are overwhelming the database,' the fix is read replicas or a cache in front of RDS, not a bigger standby. If it says 'failover happened but the app kept erroring for hours,' think cached DNS. The three-tier diagram is rarely the whole question; it is the stage on which the actual fault is placed, and knowing the healthy version by heart is how you spot the broken piece quickly.
More diagrams
Sources
Practice what you just read