Monitor a Global Website on AWS
Serve a static site via CloudFront and monitor it with CloudWatch.
Introduction
30 Second Summary
Every website you visit is served from a server somewhere in the world. Production teams need to know instantly when something breaks or slows down, before their users notice.
In this project, you will host a static website on AWS, serve it globally through a content delivery network, and build a real-time monitoring dashboard with automated alerts that notify you when errors spike.
What You'll Build
A globally distributed static website with real-time monitoring using Amazon S3, CloudFront, and CloudWatch.
By the end of this project, you'll have:
- A live website served globally through CloudFront's 750+ edge locations with HTTPS and edge caching.
- A CloudWatch dashboard displaying real-time metrics for requests, error rates, and data transfer.
- A CloudWatch alarm that triggers email notifications when your website's error rate exceeds a threshold.
- Secret Mission: Enable additional CloudFront metrics and create a second alarm based on cache hit rate.
Are there any prerequisites?
You need an AWS account to complete this project. No prior AWS experience is required.
Before We Start
In this project, you'll build a static website and distribute it globally using CloudFront. Then you'll monitor it in real time using CloudWatch dashboards and alarms.
Before diving into AWS, you'll create the two website files you'll upload later. This gives you a simple landing page ready to go when it's time to deploy.
In this step, get ready to:
- Create a project folder with your website files.
- Understand what you'll build across the next four steps.
Set up your project folder
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or Command Prompt (Windows) and press Enter to open it.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir monitored-site
cd monitored-site
- Confirm the folder exists by running:
ls
- You should see an empty output since the folder is brand new.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Visual Studio Code and press Enter to open it.
- In VS Code, click File in the top menu bar.
- Click Open Folder.
- Select the monitored-site folder on your Desktop, then click Open.
Why VS Code?
VS Code makes it easy to create, edit, and save multiple files inside a folder. Any plain text editor works, but VS Code gives you syntax highlighting and a built-in file explorer.
Create the website files
Your website needs two files. An HTML file defines the page structure, and a CSS file controls how it looks.
- In the VS Code Explorer sidebar on the left, hover over the MONITORED-SITE heading.
- Click the New File icon (a page with a plus sign).
- Type index.html and press Enter.
- Paste the following code into index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Monitored Global Website</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>Hello from the Edge!</h1>
<p>This website is served globally through Amazon CloudFront and monitored in real time with CloudWatch.</p>
<div class="services">
<div class="service">
<h2>S3</h2>
<p>Private origin storage</p>
</div>
<div class="service">
<h2>CloudFront</h2>
<p>Global CDN with HTTPS</p>
</div>
<div class="service">
<h2>CloudWatch</h2>
<p>Metrics, dashboards, alarms</p>
</div>
</div>
<p class="footer">Every request to this page is tracked in real time.</p>
</div>
</body>
</html>
What does this code do?
This page has a heading, a description, and three cards highlighting the AWS services you'll use in this project: S3 for storage, CloudFront for global delivery, and CloudWatch for monitoring.
The <link rel="stylesheet" href="style.css"> line connects this page to the stylesheet you'll create next.
- Save index.html by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- Open index.html in your browser by double-clicking the file in Finder or File Explorer.
You should see plain, unstyled text with the heading "Hello from the Edge!" and three service names listed.
- Back in VS Code, hover over MONITORED-SITE in the Explorer sidebar again.
- Click the New File icon.
- Type style.css and press Enter.
- Paste the following code into style.css:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: linear-gradient(135deg, #232f3e 0%, #1a252f 100%);
color: #ffffff;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
text-align: center;
padding: 2rem;
max-width: 800px;
}
h1 {
font-size: 2.5rem;
margin-bottom: 1rem;
color: #ff9900;
}
p {
font-size: 1.1rem;
line-height: 1.6;
margin-bottom: 2rem;
color: #d1d5db;
}
.services {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
margin: 2rem 0;
}
.service {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 153, 0, 0.3);
border-radius: 12px;
padding: 1.5rem;
}
.service h2 {
color: #ff9900;
font-size: 1.3rem;
margin-bottom: 0.5rem;
}
.service p {
font-size: 0.9rem;
margin-bottom: 0;
color: #9ca3af;
}
.footer {
font-size: 0.9rem;
color: #6b7280;
margin-top: 2rem;
}
What does this code do?
The stylesheet gives the page a dark gradient background inspired by AWS branding. The heading uses AWS orange (#ff9900), and the three service cards are arranged in a responsive grid.
The * selector at the top resets default browser margins and padding so the layout looks consistent across browsers.
- Save style.css by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- Switch to your browser and refresh the page showing index.html.
You should see a dark page with an orange "Hello from the Edge!" heading and three styled service cards in a row.
Don't see any styling?
Make sure both index.html and style.css are saved in the same monitored-site folder. The HTML links to style.css using a relative path, so they must be next to each other.
Also check that the filename is exactly style.css (not styles.css or style.CSS). Filenames are case-sensitive.
help me figure out why my CSS isn't loading
Tab 1
Great. Double check you've saved both files in your monitored-site folder.
Tab 2
Here is the full index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Monitored Global Website</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h1>Hello from the Edge!</h1>
<p>This website is served globally through Amazon CloudFront and monitored in real time with CloudWatch.</p>
<div class="services">
<div class="service">
<h2>S3</h2>
<p>Private origin storage</p>
</div>
<div class="service">
<h2>CloudFront</h2>
<p>Global CDN with HTTPS</p>
</div>
<div class="service">
<h2>CloudWatch</h2>
<p>Metrics, dashboards, alarms</p>
</div>
</div>
<p class="footer">Every request to this page is tracked in real time.</p>
</div>
</body>
</html>
Here is the full style.css:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: linear-gradient(135deg, #232f3e 0%, #1a252f 100%);
color: #ffffff;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
text-align: center;
padding: 2rem;
max-width: 800px;
}
h1 {
font-size: 2.5rem;
margin-bottom: 1rem;
color: #ff9900;
}
p {
font-size: 1.1rem;
line-height: 1.6;
margin-bottom: 2rem;
color: #d1d5db;
}
.services {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
margin: 2rem 0;
}
.service {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 153, 0, 0.3);
border-radius: 12px;
padding: 1.5rem;
}
.service h2 {
color: #ff9900;
font-size: 1.3rem;
margin-bottom: 0.5rem;
}
.service p {
font-size: 0.9rem;
margin-bottom: 0;
color: #9ca3af;
}
.footer {
font-size: 0.9rem;
color: #6b7280;
margin-top: 2rem;
}
Your website files are ready. Next up, you'll upload them to an S3 bucket and serve them globally through CloudFront.
Create an S3 Bucket and CloudFront Distribution
Your website files are ready. Now you need somewhere to host them and a way to deliver them quickly to visitors anywhere in the world.
In this step, you will upload your site to Amazon S3 (a cloud storage service) and put CloudFront (a global content delivery network) in front of it. CloudFront caches your content at 750+ edge locations worldwide, so visitors load your site from a server near them instead of crossing the globe.
In this step, get ready to:
- Create an S3 bucket and upload your website files.
- Create a CloudFront distribution with Origin Access Control.
- Verify your website loads globally over HTTPS.
Create an S3 bucket and upload your website files
S3 buckets are containers that store files (called objects) in the cloud. You will create one to hold your index.html and style.css files.
- Sign in to the AWS Management Console at https://console.aws.amazon.com.
- In the search bar at the top, type S3 and select S3 from the results.
- Click Create bucket.
- For Bucket name, enter a unique name like my-monitored-site- followed by your initials (e.g., my-monitored-site-jd). Bucket names must be globally unique across all of AWS.
- For AWS Region, select US East (N. Virginia) us-east-1.
- Leave all other settings as default. Confirm that Block all public access is checked (it should be on by default).
- Scroll to the bottom and click Create bucket.
Why block all public access?
You might expect a website bucket to be public. In this project, only CloudFront will access your bucket directly. Visitors reach your site through CloudFront, never through S3. This is more secure because you have one controlled entry point instead of two.
- In the Buckets list, click the name of the bucket you just created.
- Click Upload.
- Click Add files.
- Select both index.html and style.css from your computer.
- Click Upload at the bottom of the page.
- Wait for the success message, then click Close.
You should now see both files listed in your bucket's Objects tab.
Don't see your files after uploading?
- Make sure you clicked the final Upload button (not just Add files). Adding files stages them, but they are not uploaded until you confirm.
- Check that you are viewing the correct bucket by confirming the bucket name in the breadcrumb at the top.
Still stuck? Help me troubleshoot my S3 file upload.
Create a CloudFront distribution with Origin Access Control
A CloudFront distribution tells AWS how to deliver your content globally. You will point it at your S3 bucket and set up Origin Access Control (OAC), which ensures only CloudFront can read from your bucket.
- In the AWS Console search bar, type CloudFront and select CloudFront from the results.
- Click Create distribution.
- For Origin domain, click the dropdown and select your S3 bucket (it will appear as my-monitored-site-xx.s3.us-east-1.amazonaws.com or similar).
- Under Origin access, select Origin access control settings (recommended).
- Click Create new OAC.
- In the dialog that appears, leave the defaults (Sign requests selected, signing behavior set to always). Click Create.
- Scroll down to Viewer protocol policy and select Redirect HTTP to HTTPS.
- Scroll to Default root object and enter index.html.
- Click Create distribution at the bottom of the page.
What is Origin Access Control?
OAC tells CloudFront to sign every request it sends to your S3 bucket. S3 checks the signature and only serves files to CloudFront. This means nobody can bypass CloudFront and access your bucket directly using an S3 URL.
The signing protocol is sigv4 (AWS Signature Version 4) and the signing behavior is always. These are the recommended defaults.
After creating the distribution, CloudFront displays a banner asking you to update your S3 bucket policy. You need to do this so CloudFront has permission to read from your bucket.
- Click Copy policy in the blue banner at the top of the distribution page.
- Open the S3 console in a new tab (search for S3 in the top search bar).
- Click your bucket name to open it.
- Click the Permissions tab.
- Scroll down to Bucket policy and click Edit.
- Paste the policy you copied from CloudFront into the editor.
- Click Save changes.
Don't see the blue banner with the policy?
- Return to the CloudFront console and click on your distribution ID.
- Go to the Origins tab, select your S3 origin, and click Edit.
- The policy will be shown again. Click Copy policy and apply it to your bucket.
Need more help? Help me find and apply the CloudFront bucket policy.
Verify your website loads over HTTPS
CloudFront needs a few minutes to deploy your distribution to its global edge network. Once deployed, your website will be accessible worldwide over HTTPS.
- Return to the CloudFront console and click on your distribution.
- Watch the Last modified field in the Details section. It will show Deploying while CloudFront propagates your settings to edge locations. This takes 3-5 minutes.
- Once the status changes from Deploying to a date and timestamp, your distribution is live.
- Copy the Distribution domain name from the Details section. It looks like d111111abcdef8.cloudfront.net.
- Open a new browser tab and paste the domain name into the address bar.
- Press Enter to load your site.
You should see your website with the heading "Hello from the Edge!" displayed in orange. Check for the padlock icon in your browser's address bar. This confirms your site is served over HTTPS.
Why does HTTPS work without a certificate?
CloudFront provides a free SSL/TLS certificate for the default *.cloudfront.net domain. Every distribution gets HTTPS automatically without any certificate setup on your part.
🙋♀️ Seeing an access denied error?
- Double-check that you pasted the bucket policy from CloudFront into your S3 bucket's Permissions tab and clicked Save changes.
- Make sure the Default root object field in your distribution settings says index.html. Without this, CloudFront does not know which file to serve when you visit the root URL.
- Confirm your distribution status shows a timestamp (not Deploying). Changes take 3-5 minutes to propagate.
Still stuck? Help me fix my CloudFront access denied error.
Your website is now live on a global CDN with HTTPS enforced. Next up, you will generate traffic and explore the real-time metrics that CloudFront automatically sends to CloudWatch.
Explore CloudFront Metrics in CloudWatch
Your website is now live and accessible worldwide through CloudFront.
But how do you know if your site is actually being used, or if visitors are hitting errors? In production, teams rely on real-time metrics to answer these questions. In this step, you will generate traffic to your distribution and explore the metrics that CloudWatch collects automatically.
In this step, get ready to:
- Generate successful and error traffic to your CloudFront distribution.
- View default metrics in the CloudFront Monitoring console.
- Explore the same metrics in the CloudWatch console.
Generate traffic to your distribution
CloudWatch metrics need data points before they can show you anything useful. Right now your distribution has zero traffic, so the graphs are empty.
You will send a batch of requests using curl in your terminal to simulate real visitors.
- Open your terminal by pressing Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
- Send 20 successful requests to your site by running this command:
macOS
for i in $(seq 1 20); do curl -s -o /dev/null -w "%{http_code}\n" "https://[[CLOUDFRONT_DOMAIN="d111111abcdef8.cloudfront.net"]]/"; done
Windows
1..20 | ForEach-Object { curl.exe -s -o NUL -w "%{http_code}`n" "https://[[CLOUDFRONT_DOMAIN="d111111abcdef8.cloudfront.net"]]/" }
You should see 20 lines printed, each showing 200 (the HTTP status code for success).
What does this command do?
This loop sends 20 individual HTTP requests to your CloudFront URL and prints only the status code for each one.
- -s runs curl in silent mode (no progress bars).
- -o /dev/null discards the response body so you only see the status code.
- -w "%{http_code}\n" tells curl to print only the HTTP response code.
- Now generate some error traffic by requesting a page that does not exist:
macOS
for i in $(seq 1 5); do curl -s -o /dev/null -w "%{http_code}\n" "https://[[CLOUDFRONT_DOMAIN="d111111abcdef8.cloudfront.net"]]/nonexistent"; done
Windows
1..5 | ForEach-Object { curl.exe -s -o NUL -w "%{http_code}`n" "https://[[CLOUDFRONT_DOMAIN="d111111abcdef8.cloudfront.net"]]/nonexistent" }
You should see 5 lines showing 403. S3 returns a 403 status for missing objects when Origin Access Control is used. CloudFront counts this as a 4xx error in its metrics.
Why generate errors on purpose?
In production, 4xx errors happen when users visit broken links or mistype URLs. By creating some intentional errors now, you will have a visible spike in the error rate graph that proves your monitoring is working.
🙋♀️ Seeing 'command not found' for curl?
On macOS, curl is pre-installed. If you see this error on Windows, make sure you are using curl.exe (not just curl) in PowerShell. The bare curl command in PowerShell is an alias for a different tool.
Help me fix my curl command
View metrics in the CloudFront Monitoring console
CloudFront automatically tracks every request to your distribution. These default metrics are completely free and require no setup.
- Switch back to the AWS Management Console in your browser.
- Navigate to the CloudFront console using the search bar at the top.
- Click Monitoring in the left sidebar.
- Select your distribution from the list.
- Click View distribution metrics.
Wait 2-3 minutes for your traffic to appear in the graphs. You should see spikes in the Requests graph and a visible bump in the 4xx error rate graph from your intentional error requests.
What metrics are shown here?
CloudFront provides these default metrics at 1-minute granularity, at no additional cost:
- Requests tracks the total number of viewer requests.
- 4xx error rate shows the percentage of requests returning client errors.
- 5xx error rate shows the percentage of requests returning server errors.
- Total error rate combines both 4xx and 5xx.
🙋♀️ Still seeing empty graphs?
Metrics can take 2-5 minutes to appear after traffic is generated. Make sure you selected the correct distribution. If the graphs are still empty after 5 minutes, try sending another batch of requests from your terminal.
Help me see my CloudFront metrics
View the same metrics in the CloudWatch console
The CloudFront Monitoring page is convenient, but CloudWatch is where you build dashboards and alarms. CloudFront metrics are only available in the US East (N. Virginia) region in CloudWatch.
- Open the CloudWatch console at https://console.aws.amazon.com/cloudwatch/.
- Check the region selector in the top-right corner of the console. Make sure it says US East (N. Virginia).
- If it shows a different region, click it and select US East (N. Virginia).
- In the left sidebar, click Metrics, then click All metrics.
- Under AWS namespaces, click CloudFront.
- Click DistributionId as the dimension.
- Find your distribution in the list and check the boxes for Requests, 4xxErrorRate, and BytesDownloaded.
The graph at the top updates to show all three metrics plotted together. You should see your 4xx error rate spike clearly alongside your request count.
Why must I use the US East (N. Virginia) region?
CloudFront is a global service, but it publishes all its metrics exclusively to the us-east-1 region in CloudWatch. If you browse CloudWatch in any other region, you will not find CloudFront metrics.
🙋♀️ Don't see CloudFront in the namespace list?
Double-check that your region is set to US East (N. Virginia) in the console header. CloudFront metrics only appear in this region. Also ensure you have waited at least 2-3 minutes since generating your traffic.
Help me find my CloudFront metrics in CloudWatch
You now have visibility into your distribution's real-time performance. Next up, you will turn these metrics into a permanent monitoring dashboard.
Build a CloudWatch Dashboard
In the previous step, you explored your CloudFront metrics in CloudWatch and confirmed that traffic data is flowing. You saw requests, error rates, and bytes downloaded plotted on graphs.
Graphs in the metrics explorer are temporary. Every time you navigate away, you lose them. A CloudWatch dashboard gives you a permanent, at-a-glance view of your CDN health that you can return to any time.
In this step, get ready to:
- Create a CloudWatch dashboard named My-CDN-Dashboard.
- Add a Line widget showing Requests over time.
- Add Line and Number widgets for error rate and bytes downloaded.
Create the dashboard and your first widget
A dashboard is a collection of widgets. Each widget displays one or more metrics as a graph or number. You will start by creating the dashboard itself, then immediately add your first widget.
- In the CloudWatch console, click Dashboards in the left navigation pane.
- Click Create dashboard.
- In the Create new dashboard dialog box, enter My-CDN-Dashboard as the name.
- Click Create dashboard.
An Add to this dashboard dialog box appears, asking you to choose your first widget type.
- Select Line as the widget type.
- Click Configure.
What is a CloudWatch dashboard?
A dashboard is a customizable page in CloudWatch that displays widgets showing real-time metric data. Think of it as a control panel for your infrastructure.
The free tier includes 3 custom dashboards with up to 50 metrics each. This project uses just 1 dashboard with 3 metrics.
Add the Requests metric to the widget
The metric selection screen lets you browse all available AWS metrics. You need to drill down to your specific CloudFront distribution.
- In the Browse tab, select AWS/CloudFront.
- Select DistributionId as the dimension.
- Find and select your distribution from the list.
- Check the box next to the Requests metric.
- Click Create widget.
The widget appears on your dashboard showing request counts over time. You should see the spike from your earlier traffic generation.
What does this widget show?
The Requests metric counts how many HTTP/HTTPS requests hit your CloudFront distribution. Each data point represents the total requests received in a 1-minute window.
🙋♀️ Don't see any data in the widget?
Metrics can take 2-3 minutes to appear after traffic is generated. Wait a moment and refresh the dashboard.
If you still see nothing, confirm you are in the US East (N. Virginia) region. CloudFront metrics only appear in this region within CloudWatch.
help me troubleshoot why my CloudWatch dashboard widget shows no data for my CloudFront distribution
Add two more widgets and save the dashboard
Your dashboard currently has one widget. Production dashboards typically show multiple metrics side by side so you can correlate patterns. You will add a widget for error rate and another for total bytes downloaded.
- Click the + button at the top of the dashboard to add a new widget.
- Select Line as the widget type and click Next.
- Select Metrics.
- In the Browse tab, navigate to AWS/CloudFront and select DistributionId.
- Select your distribution from the list.
- Check the box next to 4xxErrorRate.
- Click Create widget.
Now add the third widget for bytes downloaded.
- Click the + button again to add another widget.
- Select Number as the widget type and click Next.
- Select Metrics.
- In the Browse tab, navigate to AWS/CloudFront and select DistributionId.
- Select your distribution from the list.
- Check the box next to BytesDownloaded.
- Click Create widget.
Your dashboard now has 3 widgets. Save it so it persists.
- Click Save dashboard in the upper right area of the page.
Why a Number widget instead of a Line?
A Number widget displays a single aggregate value (like total bytes transferred) rather than plotting values over time. It gives you a quick, at-a-glance summary without the detail of a time-series line.
The Line widgets for Requests and 4xxErrorRate are better as time-series graphs because you want to spot trends and spikes over time.
🙋♀️ Dashboard not saving?
Make sure you click Save dashboard (not just Create widget). Creating a widget adds it to the canvas, but the dashboard itself is not persisted until you explicitly save.
help me figure out why my CloudWatch dashboard is not saving
Your monitoring dashboard is live. You now have a permanent view of your CDN health. Next up, you will create a CloudWatch alarm that automatically alerts you when something goes wrong.
Create a CloudWatch Alarm
Your dashboard gives you visibility into how your CloudFront distribution is performing. But dashboards only help if someone is watching them.
In production, teams need automated alerts that fire when something goes wrong. A CloudWatch alarm monitors a metric continuously and triggers a notification the moment it crosses a threshold you define.
In this step, get ready to:
- Create a CloudWatch alarm on the 4xx error rate metric.
- Set up email notifications via SNS.
- Trigger the alarm with intentional error traffic and verify the alert fires.
Select the metric for your alarm
Every alarm starts by selecting which metric to watch. You will alarm on the 4xx error rate so you get notified whenever visitors hit broken links or missing pages.
- In the CloudWatch console, click Alarms in the left navigation pane.
- Click All alarms.
- Click Create alarm.
- Click Select metric.
- In the metric browser, select CloudFront under the AWS namespaces.
- Click DistributionId as the dimension.
- Find your distribution in the list and check the box next to 4xxErrorRate.
- Click Select metric.
What is 4xxErrorRate?
This metric tracks the percentage of viewer requests that resulted in a 4xx HTTP error (like 403 or 404). A spike means visitors are requesting content that does not exist or cannot be accessed.
Configure the alarm conditions
Now you will define exactly when this alarm should fire. You want it to trigger quickly so you catch error spikes within one minute.
- Under Statistic, select Average.
- Under Period, select 1 minute.
- Under Conditions, select Greater than.
- Enter 5 as the threshold value.
- Click Additional configuration to expand the extra settings.
- Set Datapoints to alarm to 1 out of 1.
- Set Missing data treatment to Treat missing data as not breaching.
- Click Next.
Why treat missing data as not breaching?
The 4xxErrorRate metric only has data when there are requests to your distribution. If nobody is visiting your site, there is no data to report. Treating missing data as "not breaching" prevents the alarm from falsely firing during quiet periods.
Set up notifications and trigger the alarm
An alarm is only useful if it notifies the right people. You will create an SNS topic that sends you an email whenever the alarm fires.
- Under Notification, confirm In alarm is selected as the alarm state trigger.
- Select Create new topic.
- Enter cdn-error-alerts as the topic name.
- Enter your email address in the Email endpoints field.
- Click Create topic.
- Click Next.
- Enter High-4xx-Error-Rate as the alarm name.
- Click Next.
- Review your settings on the Preview and create page, then click Create alarm.
What is SNS?
Amazon Simple Notification Service (SNS) is a messaging service that pushes alerts to subscribers. When your alarm fires, CloudWatch publishes a message to the SNS topic, which forwards it to every confirmed subscriber (your email).
- Check your email inbox for a message from AWS Notifications.
- Click the Confirm subscription link in that email.
Don't see the confirmation email?
Check your spam or junk folder. The email comes from no-reply@sns.amazonaws.com. If you do not confirm, SNS cannot deliver alarm notifications to you.
Help me find my SNS confirmation email.
Now trigger the alarm by flooding your distribution with requests to non-existent paths.
- Send 30 error requests to your distribution by running this command in Terminal:
for i in $(seq 1 30); do curl -s -o /dev/null "https://[[DISTRIBUTION_DOMAIN="your CloudFront domain e.g. d111111abcdef8.cloudfront.net"]]/does-not-exist-$i"; done
What does this command do?
- The loop sends 30 requests, each to a unique path like /does-not-exist-1, /does-not-exist-2, etc.
- Since none of these files exist in your S3 bucket, every request returns a 4xx error.
- This pushes the 4xxErrorRate well above 5%, which is the threshold you set.
- Wait 2-3 minutes for CloudWatch to evaluate the new data.
- Return to the CloudWatch console.
- Click Alarms, then All alarms.
- Verify that your High-4xx-Error-Rate alarm shows In alarm state (highlighted in red).
- Click the alarm name to open its details.
- Scroll down to History and confirm you see the state transition from OK to ALARM.
- Check your email. You should have received an alarm notification from SNS.
Alarm still showing OK after 3 minutes?
CloudWatch evaluates CloudFront metrics at 1-minute granularity, but there can be a short delay before data appears. Wait another 2 minutes and refresh the page.
If the alarm remains in OK state, verify that your curl command returned 403 or 404 responses. Run one request manually to check:
My CloudWatch alarm won't trigger after sending error requests.
Secret mission
Enable Additional Metrics and a Cache Hit Rate Alarm
Your dashboard monitors errors and traffic, but what about caching performance? In this secret mission, you will enable CloudFront's additional metrics to unlock the CacheHitRate metric, then build a second alarm that fires when your cache performance drops below 50%.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project stays within the AWS free tier for a personal site with low traffic, so there are no ongoing costs as long as usage remains within those limits.
Resources you used:
- S3 bucket (stores your website files).
- CloudFront distribution (serves your site globally over HTTPS).
- CloudWatch dashboard (My-CDN-Dashboard).
- CloudWatch alarms (High-4xx-Error-Rate and Low-Cache-Hit-Rate).
- SNS topic (cdn-error-alerts).
Keep everything running
No action needed. Choose this if you are still actively building or experimenting with your monitoring setup.
- Your site stays live at the CloudFront domain.
- CloudFront's free tier covers 1 TB of data transfer and 10 million requests per month.
- CloudWatch's free tier covers 3 custom dashboards and 10 standard alarm metrics.
- SNS's free tier covers 1,000 email notifications per month.
- S3 storage cost is negligible for two small static files.
Pause - I'll come back to this later
Disable alarm actions so you stop receiving email notifications while keeping everything intact for later.
- In the CloudWatch console, go to Alarms.
- Select both alarms (High-4xx-Error-Rate and Low-Cache-Hit-Rate).
- Choose Actions, then Disable alarm actions.
- Your site, dashboard, and alarms remain intact. You can re-enable alarm actions anytime by selecting the alarms and choosing Enable alarm actions.
Delete - I don't want to use this again
Remove all project resources completely. Follow these steps in order.
- Delete the CloudWatch alarms: open the CloudWatch console, choose Alarms in the navigation pane, select the checkboxes next to High-4xx-Error-Rate and Low-Cache-Hit-Rate, choose Actions, then Delete. Confirm by choosing Delete.
- Delete the CloudWatch dashboard: in the CloudWatch console, choose Dashboards in the navigation pane, select My-CDN-Dashboard, and choose Delete. Confirm the deletion.
- Delete the SNS topic: open the Amazon SNS console, choose Topics in the left navigation pane, select cdn-error-alerts, and choose Delete. In the confirmation dialog, enter delete me and choose Delete.
- Disable the CloudFront distribution: open the CloudFront console, select the checkbox next to your distribution, choose Disable, and confirm by choosing Yes, Disable. Wait a few minutes until the Last modified column shows a new timestamp.
- Delete the CloudFront distribution: select the checkbox next to the now-disabled distribution, choose Delete, and confirm by choosing Delete.
- Empty and delete the S3 bucket: open the S3 console, click on your bucket name, choose the Objects tab, select all objects, choose Delete, type permanently delete to confirm, then choose Delete objects. Return to the bucket list, select your bucket, choose Delete, type the bucket name to confirm, and choose Delete bucket.
Nice Work!
Nice Work!
Nice work! You just built a globally distributed, monitored static website using AWS S3, CloudFront, and CloudWatch.
You've learned how to:
- Deployed a CloudFront distribution serving your website globally over HTTPS with edge caching, backed by a private S3 bucket secured with Origin Access Control.
- Built a CloudWatch dashboard with real-time widgets visualizing requests, error rates, and data transfer for your CDN.
- Created a CloudWatch alarm on 4xx error rate with email notifications via SNS, then triggered and verified the full monitoring pipeline end-to-end.
- Secret Mission: Enabled additional CloudFront metrics, monitored cache hit rate, and created a second alarm.
Ready to quiz yourself?