AWS has over 200 services. If you try to learn every one of them, you will end up more overwhelmed and confused than when you started.
Here is the truth nobody tells beginners: in the real world, 15 to 25 AWS services handle the vast majority of what companies actually use to build their cloud infrastructure. Once you understand what those services are and how they connect, you can walk into an interview and talk through a system like someone who has actually built one.
So instead of a service-by-service glossary, this guide takes one complete real-world application and breaks down exactly how it works on AWS.
The application is a live-event ticketing platform — concerts, festivals, sports. I chose it deliberately, because ticketing forces you to understand AWS properly. When a major artist announces a tour you do not get normal traffic. You get millions of people hitting the site at the same moment. That means:
- The page has to load fast, everywhere in the world
- The servers have to survive a sudden, enormous spike
- The database has to answer thousands of requests per second
- The system must never sell the same seat twice
- The customer still expects their confirmation email immediately
We will follow one customer through ten steps, from the moment they type the address to the confirmation landing in their inbox. At each step you will see which service is involved, what problem it solves, and why it was chosen over the alternatives.
That last part is what actually matters. Every service on this diagram exists because without it, something breaks.
The 10 steps at a glance
| Step | What happens | AWS services |
|---|---|---|
| 1 | Customer finds the site | Route 53 |
| 2 | Page loads fast worldwide | S3 + CloudFront |
| 3 | Request enters our network | VPC + subnets |
| 4 | Traffic gets distributed | ALB + Auto Scaling |
| 5 | Application processes it | EC2 |
| 6 | Event details load | RDS |
| 7 | Seat availability checked | DynamoDB |
| 8 | Purchase processed safely | SQS FIFO + DynamoDB |
| 9 | Confirmation sent | Lambda + SES |
| 10 | Secured, monitored, reproducible | IAM, Security Groups, CloudWatch, IaC |
Free assessment
Find the AWS domains holding you back.
Get a focused study plan based on your real weak spots — not another generic course checklist.
Step 1 — How the customer finds us (Route 53)
A customer wants tickets. They open a browser and type livetickets.com.
Our platform runs on computers we rent from AWS, sitting in a data centre. Every one of those machines has an address — not a postcode, but a string of numbers called an IP address.
So when the customer types the domain name, the browser needs to work out which numbers that name points to. That translation is handled by DNS, the Domain Name System. The browser asks "where is livetickets.com?" and DNS answers.
The AWS service that handles this is Route 53. We register the domain there, tell it which destination to point at, and Route 53 serves the DNS records that send customers the right way.
One nuance worth knowing: that answer is often already cached by the browser, the device or the internet provider, so Route 53 is not contacted on every single visit. It is still the service behind the record that directs traffic.
We do not point customers straight at the servers running the application. We point them at CloudFront — which is step 2.
Step 2 — The page loads fast, everywhere (S3 + CloudFront)
The browser has reached our platform and needs to load the page.
A web page is not one item. It is many separate files — images, layout, styling, text, buttons. The browser downloads them individually and assembles what you see.
Some of those files are identical for every visitor: the logo, the layout, the styling. These are static files.
The rest is dynamic content: "3 tickets remaining", "logged in as Sarah". That differs per user, so it has to be worked out fresh each time by our application servers. That is real processing work.
Because these two types behave so differently, we handle them separately. Static files go somewhere cheap and fast. Dynamic content stays with the application servers. We do not want servers burning capacity delivering banner images to every visitor.
Where static files live: S3
S3 — Simple Storage Service — is file storage in the cloud. Effectively unlimited, extremely durable, and cheap. We upload images, layouts, seat maps and styling once, and they are available whenever anything needs them.
But there is a problem. S3 stores objects in one AWS Region. A Region is simply a geographic area where AWS runs data centres. If our bucket is in London and a customer opens the site in Australia, their browser is reaching all the way to London and back just to load the page.
On a ticketing platform, when a major tour has just dropped and every second counts, a slow page means people abandon before they can buy. That is lost revenue — and it is the pattern you will see throughout this whole system. Every technical decision has a direct business consequence.
Where CloudFront comes in
CloudFront is AWS's content delivery network. It gets files closer to users so they load faster.
On top of the main Regions, AWS runs hundreds of smaller Edge Locations — lightweight servers spread across cities worldwide whose only job is holding copies of files near the people requesting them.
Put CloudFront in front of S3 and this happens:
- The first customer in Tokyo visits. Their request hits the nearest Edge Location in Japan.
- The files are not there yet, so CloudFront fetches them from S3 in London, serves the customer, and caches a copy at that edge.
- The next customer in Tokyo gets those files served instantly, with no round trip to London.
This repeats at every Edge Location as people visit from different places. It does not mean every file is instantly copied everywhere — it means the files people actually request get served from nearby.
CloudFront can also sit in front of dynamic traffic. When the customer searches events or buys tickets, those requests can still come through CloudFront and get forwarded to the load balancer. Static files get cached; dynamic requests get forwarded for a fresh answer.
Step 3 — The request enters our network (VPC + subnets)
The customer starts browsing — tapping an artist, filtering by city, scrolling shows. Every action sends a request to our application. This is the dynamic side, so the request needs to reach our actual servers.
But we cannot leave servers sitting open on the internet. They sit behind systems holding customer accounts and payment details. The first thing we need is control over who can get in.
That is the VPC — Virtual Private Cloud. Your own isolated network inside AWS.
The way I think about it: AWS is a massive shared building with thousands of companies running systems inside it. A VPC gives you your own private floor. Nobody else sees what is on your floor. You set the rules for what comes in and what stays out.
Inside the VPC we do not throw everything into one space. We organise it into subnets:
- Public subnets have a route to the internet through an internet gateway. This is where things that must receive internet traffic live — like the load balancer.
- Private subnets have no direct route from the internet. This is where application servers and databases live, so users cannot reach them directly.
Not everything sits inside the VPC. Some AWS services are managed by AWS outside your network, and your application reaches out to them securely when needed. We will see the first example in step 7.
Step 4 — The traffic gets distributed (ALB + Auto Scaling)
The request enters through an internet gateway — the door into our VPC — and reaches our load balancer, the Application Load Balancer (ALB).
The ALB sits in a public subnet because it is the one component that must be reachable from the internet. Every customer request comes through this single door.
An important detail: an internet-facing ALB must be placed across at least two public subnets in different Availability Zones. That is not a nice-to-have — AWS requires subnets from two or more AZs. If one data centre has a problem, traffic still flows through another.
Behind the ALB sit multiple servers running our application. The load balancer decides which one handles each request. With five servers running, it spreads traffic across all five so none gets overwhelmed. If one stops responding, the ALB notices via health checks and stops sending traffic there.
Why a load balancer is not enough
Here is the part people miss: a load balancer does not create servers. It only works with what already exists.
If half a million people arrive and you have five servers, the ALB will distribute as evenly as it can — but five servers still cannot handle half a million people. They all get overwhelmed and the platform goes down.
That is where Auto Scaling comes in. Auto Scaling watches how hard the servers are working. When load climbs past a threshold — say 70% capacity — it automatically launches more. As traffic keeps rising, more get added. When the rush subsides, it removes the extras so you stop paying for idle machines.
The two work as a pair:
- Load balancer — distributes traffic across whatever servers exist
- Auto Scaling — makes sure the right number of servers exist
Without Auto Scaling you are stuck with a fixed fleet and hope. Without the load balancer, all traffic hits one server while the rest sit idle. You need both.
Step 5 — The application processes the request (EC2)
The load balancer forwards the request to one of the servers behind it. Those are EC2 instances.
EC2 — Elastic Compute Cloud — is really just a virtual computer in an AWS data centre. You choose how powerful it is, how much memory it has, the operating system, and the software on it. It is your machine; you just do not physically own it.
This is where the application code runs. When a customer taps a concert in Manchester, the request lands on one of these servers, the application works out what they are asking for, fetches the right data, and returns it.
These instances sit in private subnets, so the customer's browser cannot reach them directly. The only path in is through the load balancer. That is deliberate — you do not expose application servers to the open internet.
Being in a private subnet does not mean cut off. They can still securely reach other AWS services, which we will see shortly.
EC2 is not the only option
Containers, via ECS or EKS, are another common approach. Containers make applications easier to package, deploy and scale consistently across environments. You could absolutely run this platform in containers.
For a beginner-level architecture, EC2 with Auto Scaling is the simpler way to understand the compute layer — full control, scales with demand.
Step 6 — The event details load (RDS)
The server needs details for this concert: artist, venue, date, seating map, pricing tiers.
All of that is structured and interconnected. When data relates to other data like this, you store it in a relational database. On AWS that is RDS — Relational Database Service.
The easiest way to picture a relational database is a set of connected spreadsheets. It can answer queries because the data is organised and the relationships between tables are defined.
RDS sits deep inside the architecture, in a private subnet, behind the application servers. It cannot be reached from the internet. The only things allowed to talk to it are the EC2 instances running our code. Your database holds your most important information — you want as few things as possible able to reach it.
The instance queries RDS, gets the event details, and the customer sees the page. They want two tickets. But before buying, one question has to be answered: are those seats still available?
Step 7 — Checking ticket availability (DynamoDB)
When half a million people are looking at the same concert, the system answers that availability question thousands of times per second.
RDS could handle this if designed carefully with transactions and locking. But for this specific access pattern — millions of simple, high-speed checks of "what is the status of this exact seat?" — DynamoDB is the better fit. We do not need complex joins here. We need fast key-based lookups and safe updates at enormous scale.
DynamoDB is a NoSQL database and works completely differently from RDS. Instead of connected tables it behaves like a fast index. Each seat is its own record: the key is the event ID plus the seat ID, and the value is the status — available, reserved or sold. Ask for a seat, get the answer instantly.
It also scales without you managing database servers.
Notice where DynamoDB sits: not inside the VPC next to RDS. DynamoDB is a regional managed service, run by AWS outside your network. This is the first example of what I mentioned in step 3. Our EC2 instances reach out to it securely, and AWS provides ways to keep that traffic private — such as a VPC Endpoint.
So we have two databases, each doing the job it is built for:
| RDS | DynamoDB | |
|---|---|---|
| Type | Relational | NoSQL key-value |
| Holds | Events, venues, pricing tiers | Individual seat status |
| Strength | Connected data, joins | Massive-volume simple lookups |
| Location | Private subnet, inside VPC | Regional managed service, outside VPC |
The customer checks. Their two seats are available. They click buy.
Step 8 — The purchase gets processed (SQS FIFO + DynamoDB)
This is the most critical moment in the entire system.
Say three people click buy on Seat 14 at almost the same instant. With no controls, all three requests race in. Each checks DynamoDB, each sees the seat available, each reserves it. Now three people believe they bought the same seat. That is double-selling, and on a ticketing platform it is a disaster.
Two things work together to prevent it.
The queue
When the customer clicks buy, the request does not go straight into reservation logic. It joins an SQS FIFO queue.
FIFO means First In, First Out — but the important detail is that ordering is handled by message group. For ticketing we group messages by the specific event and seat. So all attempts to buy Seat 14 for one event are processed in order, while purchases for different seats still happen in parallel.
The part that actually protects the seat
The queue controls flow. But the real protection is how DynamoDB handles the update.
A bad approach: check if the seat is available, then in a separate step mark it reserved. The problem is the tiny gap between check and update. In that gap another request can check the same seat and also see it available. That gap is exactly where double-selling happens.
DynamoDB removes the gap with a conditional update — check and update as one single atomic action:
"Mark this seat as reserved, but only if it is currently still available."
If the seat is free, it goes through. If someone else already took it, the update fails immediately and the customer is told the seat is gone.
Only the first request that successfully flips the seat from available to reserved wins. Every later request fails, because the condition is no longer true.
Like DynamoDB, SQS is a regional managed service outside the VPC. Our instances send messages to it securely, the same way they reach DynamoDB.
The bonus: decoupling
There is one more benefit. If the processing system goes down for a few minutes, messages do not disappear. They wait in the queue. When processing resumes, it picks up where it left off.
The part that receives purchase requests and the part that processes them are completely independent. One can fail without taking the other down. That separation is called decoupling, and it is one of the most important design decisions in cloud architecture.
Step 9 — They get a confirmation (Lambda + SES)
The purchase is confirmed. Now the customer needs the email.
We take the order details — event, seats, price — format them into an email, and send it. A couple of seconds of work, then done.
Our EC2 servers could do this, but we would be piling more onto machines already under load. Instead we hand it to something purpose-built for short tasks: AWS Lambda.
Lambda works completely differently from EC2. With EC2 you have servers running constantly, ready and waiting. With Lambda, nothing runs until something triggers it. You write the code, Lambda runs it when there is work, then it stops. If nobody is buying tickets at 3am, Lambda is not running and costs nothing.
Here, Lambda is triggered by messages from the SQS queue. When a purchase message arrives, Lambda runs the reservation logic, attempts the DynamoDB conditional update, and if the seat is successfully reserved, formats the confirmation and calls SES.
SES — Simple Email Service — is built for sending email at scale. Lambda does not send the email itself. It assembles the email and calls SES to deliver it. Lambda does the thinking, SES does the sending.
Both are regional managed services outside the VPC. Lambda does not need to be attached to your VPC unless it needs private VPC resources like RDS. In this flow it mainly talks to SQS, DynamoDB and SES through AWS service APIs, so it can run outside. If it needed the private database directly, we would attach it.
This is a trade-off pattern you will see constantly:
- EC2 — work that runs continuously and needs a full server environment
- Lambda — short tasks that fire on an event, do their job, and stop
We use both here because we have both types of work.
Step 10 — Keeping it secure, monitored and reproducible
The customer journey is done. But there is a layer running underneath all nine steps.
In reality these are not separate. Every time you set up a service you configure its permissions, lock down access and wire up monitoring at the same time. I have saved them for the end so the journey stayed readable — not because they come last.
Security: two layers
Security Groups are a set of rules on the door of each component, controlling what is allowed in and out:
- The load balancer's door is open to the internet — that is how customers reach us
- The EC2 instances' door only opens for traffic from the load balancer
- The RDS database's door only opens for the EC2 instances
An attacker cannot skip the application layer and connect straight to the database from the internet. They have to go through the path we designed. And even if one layer is compromised, we limit the blast radius with database credentials, IAM permissions, secrets management, logging and least-privilege access.
IAM — Identity and Access Management — is the second layer. Security Groups control who can connect over the network. IAM controls what each service is allowed to do once connected.
Think of keycards in a building. Every service gets one, and it only opens the doors needed for its job. Our EC2 instances get a keycard that lets them look up seats in DynamoDB and send messages to SQS. That is it. They cannot delete the DynamoDB table, cannot reach unrelated S3 buckets, cannot touch anything else in the account. Lambda gets a keycard for reading SQS and calling SES. Nothing more.
If something goes wrong with one component, the damage stays contained.
One nuance for RDS: IAM handles AWS-level permissions, but actually logging into the database and running queries is controlled by traditional database credentials. So the EC2 instance passes the Security Group to reach RDS over the network, then needs valid login credentials. Two checkpoints.
And for the managed services outside the VPC, we do not open the private subnet to the internet. AWS provides secure outbound paths — most commonly a VPC Endpoint, which lets servers reach an AWS service without traffic leaving AWS's network. Private does not mean cut off. It means the internet cannot reach in, but our servers can still reach out.
Monitoring: CloudWatch
The system is live. Half a million people are on the platform. How do you know it is working?
CloudWatch collects metrics and logs from AWS services — EC2 CPU, load balancer request counts, errors, latency, application logs. For business metrics like tickets purchased per minute, the application publishes custom metrics. For real user page speed, CloudWatch RUM shows what customers actually experience in their browser.
That feeds dashboards — a control room showing the health of every part at a glance — and alarms. If error rates spike, the team is notified immediately.
Some alarms trigger automatic responses. If servers are under heavy load, an alarm tells Auto Scaling to add capacity without anyone lifting a finger.
Infrastructure as Code
In a real cloud engineering job, none of this gets built by clicking through the AWS console.
Here is why. Say you spent days configuring this by hand. It works. Three months later someone asks for an identical copy for testing. You cannot remember every setting. You miss something. Your test environment does not match production — so when something breaks in testing, it tells you nothing useful.
Infrastructure as Code solves this. Instead of clicking, you write a file describing everything: every service, its configuration, its connections, its permissions. You hand that file to Terraform or CloudFormation and it builds exactly what you described.
Need a testing copy? Same file. Need to rebuild in another Region? Same file. Every environment is identical because they come from the same source. And because it is a file, you can track every change — who changed what, when, and why.
The complete journey
- Customer types the URL. Route 53 resolves the domain and points to CloudFront.
- CloudFront serves static files from the nearest Edge Location, pulling from S3. The page loads fast anywhere.
- Browsing requests enter our VPC through the public subnet toward the private subnet.
- The ALB spreads traffic across servers; Auto Scaling ensures enough exist.
- An EC2 instance picks up the request and processes it.
- The server queries RDS for event details.
- Seat availability is checked in DynamoDB — instant response.
- On buy, the request enters an SQS FIFO queue grouped by event and seat, then DynamoDB's conditional update reserves the seat only if still available. This is what prevents double-selling.
- Lambda processes the confirmed purchase and calls SES to deliver the confirmation.
- Underneath it all, Security Groups and IAM control every connection and permission, CloudWatch monitors health, and the whole thing is built with IaC.
The takeaway that actually matters
You do not learn AWS by memorising services. You learn it by understanding the problems they solve.
Every service in this architecture exists because without it something breaks. Remove Auto Scaling and the launch day crashes. Remove the conditional update and you sell the same seat three times. Remove CloudFront and customers on the other side of the world abandon before the page renders.
For any service you choose, be ready to justify what problem it solves and why you picked it over the alternatives. That is the difference between someone who has watched a course and someone who can architect.
Once you start thinking about AWS as problems and the services that solve them, everything changes — including how the exam questions read.