Cloud Infrastructure: Building a Three-Tier Architecture with EC2, S3, and RDS
Starting from a single server that does everything, this post breaks the stack apart into frontend, application, and data tiers, mapped onto AWS's EC2, S3, and RDS — and explains why this old-school pattern is still the default today.
Say you're launching a website: user-uploaded images, the code running your business logic, and the database holding member data are all crammed onto a single EC2 instance. Fine when traffic is light. But once it picks up, you run into an awkward problem — the database maxes out the CPU, and suddenly the webpage won't load either, because they're fighting over the same machine's resources.
That's exactly the problem a three-tier architecture solves. It's not some cutting-edge idea — it might be the most traditional, most basic architecture pattern in cloud computing — but that's precisely why it's usually the first thing engineers reach for when designing a system. This post builds it out concretely using three AWS services: EC2, S3, and RDS.
What does a three-tier architecture actually split up?
Think of it like how a restaurant divides labor: the front of house talks to customers, takes orders, and serves food; the kitchen turns ingredients into dishes; the storeroom holds ingredients and handles restocking. Each role sticks to its own job — the front of house doesn't run into the kitchen to cook, and the kitchen doesn't step out to greet customers. If more customers show up, you can just hire more front-of-house staff without doubling the entire restaurant's headcount.
Mapped onto a system architecture, that's the three tiers:
- Presentation Tier: what users actually see and interact with — the HTML, CSS, and JavaScript of a webpage, plus static assets like images and videos.
- Application Tier (also called the Logic Tier): where business logic runs — validating logins, calculating order totals, calling other services.
- Data Tier: where data lives, usually a relational database handling reads, writes, and persistence.
The three tiers only talk to each other through well-defined interfaces. The presentation tier never touches the database directly, and the data tier doesn't care what the UI looks like. This separation lets each tier scale independently, get maintained independently, and even swap out its tech stack without touching the others.
Tier one: hand the Presentation Tier to S3
If your frontend is a purely static site — say, HTML/CSS/JS bundled out of React — you don't need a server running at all. Just drop it into S3 (Simple Storage Service). S3 is AWS's object storage service; think of it as a massive filing cabinet — you throw files in, and it hands you a URL to access them.
Pair S3's static website hosting with a CloudFront CDN in front of it for caching and acceleration, and users pull assets from whichever edge node is closest to them — much faster, and you don't have to worry about the presentation tier buckling under a traffic spike, since S3 itself is highly available and auto-scaling. You never have to think about how many machines are behind it.
Tier two: EC2 carries the Application Tier
Once the frontend renders the data, the actual number-crunching belongs to the application tier. This tier typically runs on EC2, because business logic usually needs a long-running server process — an API service written in Node.js, Java, or Python — handling things like login validation, order calculations, and third-party integrations.
A single EC2 instance hits the same traffic bottleneck, so in practice you don't run just one — you pair it with an Auto Scaling Group: spin up more EC2 instances automatically when traffic climbs to spread the load, and shut some down automatically when it drops to save money. In front of that sits an Application Load Balancer, distributing incoming requests evenly across the fleet of EC2 instances. Users never know which machine actually handled their request.
This tier belongs in a private subnet inside your VPC (Virtual Private Cloud), not exposed directly to the public internet — only the load balancer routes traffic in. This matters a lot for security: if you're setting this up yourself, remember the application tier's EC2 instances don't need a public IP, and shouldn't have one.
Tier three: RDS is home for the Data Tier
The data tier handles long-term storage, and here we reach for RDS (Relational Database Service) — AWS's managed relational database service, supporting engines like MySQL, PostgreSQL, and MariaDB. Compared to installing a database on EC2 yourself, RDS takes the tedious-but-critical operational work off your plate: backups, patching, failover.
RDS's Multi-AZ feature automatically maintains a synced standby replica in a different Availability Zone. If the primary database runs into trouble, AWS fails over to the standby automatically, and you barely notice the interruption. Like the application tier, the data tier should sit in a private subnet — usually one layer deeper than the application tier — allowing connections only from the application tier's EC2 instances. The database shouldn't have any path to the public internet at all.
Why not just cram everything together?
Back to the question from the start: splitting things into three tiers sounds like more work, doesn't it? Fair enough — setup cost and operational complexity both go up. But the payoff is just as direct:
- Independent scaling: when traffic spikes, it's usually the application tier that feels the pressure first. You just add more EC2 instances — no need to duplicate the database or the frontend assets along with it.
- Security isolation: the database is never exposed to the public internet, so even if the application tier gets compromised, an attacker still can't reach it directly.
- Clear ownership: frontend engineers changing the UI won't touch backend logic, and backend engineers changing business logic won't touch the database schema — teams can work in parallel without stepping on each other.
- Fault tolerance: if an EC2 instance goes down, the Auto Scaling Group replaces it automatically; if the primary database goes down, Multi-AZ fails over automatically. Users barely feel the disruption.
These benefits might not feel obvious when traffic and the team are both small. But the moment your system grows even a little, the operational cost a three-tier architecture saves you will far outweigh the complexity of setting it up.
Wrapping up
The core idea behind a three-tier architecture really comes down to one thing: don't cram different responsibilities into the same place. The presentation tier makes sure users can see things and use them smoothly (S3 plus CloudFront), the application tier handles the business logic (EC2 plus Auto Scaling), and the data tier keeps the data safely stored (RDS plus Multi-AZ). VPC subnetting and security groups gatekeep the boundaries between the three, letting each tier scale and get maintained independently — and keeping security risk from ever creeping all the way down to the core database.