Build Instant Failover with CloudFront Origin Groups
Build automatic failover that switches regions in seconds, not minutes. The same pattern DAZN and Twitch use to maintain uptime during outages.
Introduction
This project has been archived
We're no longer updating this project - we recommend checking out our active projects instead!
If you've already completed this project, don't worry! Your documentation is still available for you to check out and share.
If you have any questions, leave a question in our Discord and we'll get back to you ASAP!
⚡️ 30 second Summary
When your primary server goes down, how long does it take for traffic to switch to a backup? With traditional DNS-based failover, you're looking at minutes of downtime while DNS records propagate across the internet. During the 2021 Fastly CDN outage, sites like Twitch and HBO Max went down for nearly an hour - costing millions in lost revenue.
This is why companies like DAZN (streaming sports to 200+ countries) and Twitch (99.99% availability target) use edge-based failover. CloudFront origin groups detect failures and route traffic to healthy servers in seconds, not minutes. Failover happens at edge locations worldwide - no DNS changes, no manual intervention.
You'll build this exact pattern: a CloudFront distribution that automatically routes traffic between two AWS regions. When one fails, traffic switches instantly. When it recovers, traffic returns automatically. This is how production systems serving billions of requests maintain uptime SLAs.
What you'll build
In this project, you'll configure CloudFront origin groups to provide automatic failover between your AWS App Runner services in us-east-1 and us-west-2.
By the end of this project, you'll have:
- A CloudFront distribution with origin failover configured
- Automatic failover that switches regions in seconds when the primary fails
- Automatic failback that returns to the primary when it recovers
- 💎 Secret Mission: CloudWatch alerting that notifies you when failovers occur
Prerequisite: Multi-Region Deployment
This project builds on the Deploy Multi-Region project. You'll need two AWS App Runner services running - one in us-east-1 and one in us-west-2, both responding with their region name.
Haven't completed that project yet? Start with Deploy Multi-Region first.
💡 New to CloudFront?
CloudFront is AWS's content delivery network (CDN). It caches and serves your content from 400+ edge locations around the world, reducing latency for users everywhere.
But CloudFront isn't just for caching - it's also a powerful routing layer. Origin groups let you define primary and secondary origins, with automatic failover when the primary becomes unhealthy. DAZN uses this exact feature to ensure live sports streams keep running even when backend systems fail during traffic spikes.
You don't need any prior CloudFront experience. This project teaches you how origin groups work and how to configure failover that happens in seconds.
Not sure if this project is right for you? Check if it matches your goals.
Want a complete demo of how to do this project, from start to finish? Check out our 🎬 walkthrough with Kahu or 🎬 fast track it with Maximus
If you're up for a bit of a challenge, quiz yourself on the key concepts up ahead in this project! Don't be too nervous, you'll also get a quiz at the end of this project, to recap what you've learned.
This project is part of a series:
- Part 1: Build Multi-Region Apps on AWS (required)
Before we start Step #1...
This project builds on the Deploy Multi-Region project. Before we start, let's make sure you have two AWS App Runner services running - one in us-east-1 and one in us-west-2.
✅ I've done Project #1
You already have two App Runner services running in us-east-1 and us-west-2. Let's add CloudFront failover!
❌ I need to set up App Runner first
No problem! Let's quickly deploy your app to both regions before setting up CloudFront.
Set Up GitHub Repository
- Go to github.com and sign in (or create an account if needed).
- Click your profile picture → Repositories → New.
- Name it multi-region-app, select Private, and click Create repository.
- Copy the HTTPS URL from the quick setup page.
Paste your repository URL here: [[YOUR_REPO_URL="https://github.com/YOUR_USERNAME/multi-region-app.git"]]
Clone and Create Your App with Cursor
- If you don't have Cursor installed, download it from cursor.com.
- Open Cursor and press Cmd+Shift+P (Mac) or Ctrl+Shift+P (Windows) to open the command palette.
- Type Git: Clone, press Enter, and paste your repo URL: [[YOUR_REPO_URL="https://github.com/YOUR_USERNAME/multi-region-app.git"]]
- Select a folder to clone into, then click Open when prompted.
✅ It's working
Great! Your repository is cloned and ready. Let's move on.
❌ Getting an error?
That's totally okay! This just means you don't have Git installed on your computer.
- Head over to git-scm.com/downloads.
- Download and run the installer for your operating system.
- Once installed, restart your IDE and try again.
Still having issues? Troubleshoot here or share your error with the NextWork community!
Create Your Express App with AI
- Open Cursor chat (Cmd+L / Ctrl+L) and send this prompt:
Create a simple Express.js web server I can deploy to AWS App Runner. I need a package.json with the Express dependency and an index.js that listens on process.env.PORT (or 8080 as fallback). Just a single route at "/" that returns "Hello from AWS!" is fine. Make sure there's a start script so App Runner can run it.
- Click Accept to add the files.
Push to GitHub
- Open the terminal in Cursor (Ctrl+`) and run:
git add .
git commit -m "Add Express app"
git push
✅ It's working
Great! Your code is pushed to GitHub. Let's move on.
❌ Getting an error?
Getting an authentication error?
Install GitHub CLI, run gh auth login, then try git push again.
Get help with GitHub authentication or share your error with the NextWork community!
Deploy to App Runner (us-east-1)
- Go to App Runner in the us-east-1 region.
- Click Create service.
- Select Source code repository and GitHub as provider, then click Add new.
- Name the connection github-connection-east and click Install another.
- In GitHub, select your multi-region-app repository and click Install & Authorize.
- Back in AWS, select your GitHub app and click Next.
- Select your repository and main branch.
- Select Automatic deployment and click Next.
- Configure build: Runtime = Nodejs 18, Build command = npm install, Start command = npm start, Port = 8080.
- Click Next.
- Name the service multi-region-app-east.
- Click Next, then Create & deploy.
Wait 2-3 minutes for deployment. Once Running, verify you see "Hello from AWS!"
Deploy to App Runner (us-west-2)
- Switch to the us-west-2 region in the AWS Console (top right corner).
- Go to App Runner and click Create service.
- Select Source code repository and GitHub as provider, then click Add new.
- Name the connection github-connection-west.
- Select your GitHub account from the GitHub app dropdown (already installed).
- Click Next, then select your repository and main branch.
- Select Automatic deployment and click Next.
- Configure build: Runtime = Nodejs 18, Build command = npm install, Start command = npm start, Port = 8080.
- Click Next.
- Name the service multi-region-app-west.
- Click Next, then Create & deploy.
Wait for deployment. Once Running, verify both region URLs show "Hello from AWS!"
Create a CloudFront Distribution
Time to build the same failover pattern DAZN uses to stream live sports! You'll set up CloudFront with an origin group that automatically routes traffic to your secondary region when the primary fails. This is how production systems achieve sub-second failover - no DNS propagation delays.
What is CloudFront?
CloudFront is AWS's content delivery network (CDN). It has edge locations around the world that cache and serve your content closer to users. But CloudFront isn't just for caching - it can also route traffic between multiple backend servers (called "origins") and automatically switch between them when one fails. This is the feature we'll use to build automatic failover.
In this step, get ready to:
- Gather your App Runner URLs
- Create a CloudFront distribution with your primary origin
Gather Your App Runner URLs
Before creating the CloudFront distribution, let's grab the URLs for both App Runner services.
- Go to the AWS Console.
- In the search bar, type App Runner.
- Select App Runner from the results.
- Make sure you're in the us-east-1 region (top right corner).
- Click on your App Runner service.
- Copy the Default domain URL (e.g., xxxxxxxx.us-east-1.awsapprunner.com).
[[YOUR_EAST_URL="your-service.us-east-1.awsapprunner.com"]]
- Switch to the us-west-2 region (top right corner).
- Click on your App Runner service.
- Repeat the same process - copy the Default domain URL for your west region service.
[[YOUR_WEST_URL="your-service.us-west-2.awsapprunner.com"]]
Navigate to CloudFront
First, let's access CloudFront in the AWS Console.
- Open the AWS Console.
- In the search bar, type CloudFront.
- Select CloudFront from the results.
Create a New Distribution
Now let's create a CloudFront distribution that will serve as your global entry point.
- Click Create distribution.
Select Pricing
- Select Pay as you go pricing (it should already be selected).
- Click Next.
Configure Distribution Options
- For Distribution name, enter primary-us-east-1.
- For Distribution type, select Single website or app.
- Click Next.
Specify the Primary Origin
The primary origin is your us-east-1 App Runner service. CloudFront will route traffic here first.
- For Origin type, select Other (App Runner isn't listed as a specific type).
- For Origin domain, enter your App Runner URL (domain only - no https:// or trailing /):
[[YOUR_EAST_URL="your-service.us-east-1.awsapprunner.com"]]
Getting "The parameter origin name must be a domain name" error?
Remove any trailing / from the URL. It should be just your-service.us-east-1.awsapprunner.com, not your-service.us-east-1.awsapprunner.com/.
💡 What is an "origin" in CloudFront?
An origin is where CloudFront fetches content when it doesn't have a cached copy. Your origin can be an S3 bucket, an EC2 instance, a load balancer, or in our case - an App Runner service. When users request your CloudFront URL, CloudFront either serves cached content or forwards the request to your origin.
Configure Security Settings
- Scroll to Web Application Firewall (WAF)
- Review the security options available.
- Click Next to continue.
Create the Distribution
- Review your settings.
- Click Create distribution.
Wait for Initial Deployment
- Wait until Status changes from "Deploying" to "Enabled" (5-10 minutes).
- Copy your CloudFront distribution domain name (looks like d1234abcd5678.cloudfront.net).
Paste your CloudFront URL here: d1234abcd5678.cloudfront.net
Configure Origin Groups for Failover
Your CloudFront distribution is deployed with your primary origin. Now let's add the secondary origin and create an origin group that enables automatic failover between them.
In this step, get ready to:
- Add the secondary origin (us-west-2)
- Create an origin group with failover criteria
- Configure cache behavior to use the origin group
- Test your CloudFront distribution
Add the Secondary Origin
Now add your us-west-2 App Runner service as a backup origin.
- Click on your distribution to open it.
- Go to the Origins tab.
- Click Create origin.
Configure the Secondary Origin
- For Origin domain, enter your App Runner URL (without https:// or trailing /):
[[YOUR_WEST_URL="your-service.us-west-2.awsapprunner.com"]]
- For Name, enter secondary-us-west-2.
- Click Create origin.
You should see a success message confirming the secondary origin was created. You now have 2 origins.
Create an Origin Group for Failover
Origin groups enable automatic failover. When CloudFront detects the primary origin is unhealthy, it automatically routes to the secondary.
- Stay on the Origins tab of your distribution.
- Click Create origin group.
Add Origins to the Group
- Click the Choose origins to add to group dropdown.
- Select your primary origin (the us-east-1 App Runner URL).
- Click Add.
- Repeat to add your secondary origin (the us-west-2 App Runner URL).
- Ensure the primary origin is listed as 1 (primary) and the secondary as 2.
Configure Failover Criteria
- For Name, enter failover-group.
- For Failover criteria, select these HTTP status codes:
- 404 Not found
- 500 Internal server error
- 502 Bad gateway
- 503 Service unavailable
- 504 Gateway timeout
- Click Create origin group.
You should see a success message confirming the origin group was created.
What is an origin group and how does failover work?
An origin group bundles two origins together - a primary and a secondary. CloudFront always tries the primary first. If it gets one of the error codes you specified (404, 5xx), it immediately retries the same request against the secondary origin. This happens at the edge location level, so failover is nearly instantaneous - no DNS propagation delays like traditional failover.
💡 Why include 404 in failover criteria?
This is a subtle but important detail. When you pause an App Runner service, it returns 404 (not a 5xx error). If you only selected 5xx errors, CloudFront would keep trying the paused primary and never fail over! Including 404 ensures CloudFront switches to the secondary when the primary service is unavailable for any reason.
Update Cache Behavior to Use Origin Group
Now point the default cache behavior to your origin group.
- Go to the Behaviors tab of your distribution.
- Select the default behavior (the one with Default (*) path pattern).
- Click Edit.
- In the Origin and origin groups dropdown, select your failover-group.
- In the Viewer section,
- set Viewer protocol policy to HTTPS only.
- set Allowed HTTP methods to GET, HEAD, OPTIONS.
- In the Cache key and origin requests section, set:
- Cache policy to CachingDisabled.
- Origin request policy to AllViewerExceptHostHeader.
- Response headers policy to SimpleCORS.
- Scroll down and click Save changes.
Why these cache settings matter
These settings control how CloudFront handles requests between users and your origins:
- CachingDisabled: Ensures every request goes to your origin, so failover testing shows real-time results (in production, you'd enable caching for performance).
- AllViewerExceptHostHeader: This is critical! CloudFront normally forwards the original Host header (your CloudFront domain), but App Runner needs to receive its own hostname to route correctly. This policy forwards all headers except Host, letting CloudFront substitute the origin's hostname instead.
- SimpleCORS: Adds cross-origin headers so browsers can make requests from different domains.
Understanding Host header behavior is essential for DevOps - misconfigured headers are a common cause of "it works locally but not in production" issues.
Wait for Changes to Deploy
CloudFront needs to deploy your changes to all edge locations.
- Wait until Status changes from "Deploying" to "Enabled".
- This typically takes 2-5 minutes.
Test Your CloudFront Distribution
Once deployed, verify CloudFront routes to your primary origin.
- Open a new browser tab.
- Navigate to your CloudFront URL:
https://[[YOUR_CLOUDFRONT_URL="d1234abcd5678.cloudfront.net"]]
- You should see "Hello from us-east-1!" (or your primary region's response).
This confirms CloudFront is working and routing traffic to your primary App Runner service.
✅ It's working
Great! Your CloudFront distribution is working and routing to your primary origin. Let's move on.
❌ Seeing an error or wrong region?
Still seeing an error or wrong region?
If you see a CloudFront error page or the wrong region's response:
- Distribution not ready: Make sure the status is "Enabled" (not "Deploying"). It can take 5-10 minutes.
- Wrong origin domain: Check that your origin domains don't include https:// - just the hostname.
- Origin group not selected: Verify the default cache behavior is pointing to your failover-group, not an individual origin.
- Browser caching: Try an incognito/private window or clear your browser cache.
How to verify your origin group is selected:
- Go to your CloudFront distribution and click Behaviors.
- Select the default behavior and click Edit.
- Verify Origin and origin groups is set to your failover-group.
How to clear the CloudFront cache:
- Go to your CloudFront distribution and click the Invalidations tab.
- Click Create invalidation.
- Enter /* to invalidate all cached content and click Create invalidation.
Get help with CloudFront issues or share your error with the NextWork community!
Test Failover and Failback
Your CloudFront distribution is live! Now comes the exciting part - let's simulate a regional outage and watch CloudFront automatically fail over in seconds, then verify it fails back when the primary recovers. This is exactly what Twitch's engineers do to validate their "Sage Origin Backup" system that maintains 99.99% availability.
In this step, get ready to:
- Pause the us-east-1 App Runner service to simulate an outage
- Verify automatic failover to us-west-2
- Resume the primary service and verify automatic failback
Navigate to App Runner
First, access your us-east-1 App Runner service.
- In the AWS Console, search for App Runner.
- Select App Runner.
- Make sure you're in the us-east-1 region (check the region selector in the top right).
- Click on your App Runner service name.
Pause the Primary Service
Pausing simulates a regional outage. The service stops responding, triggering CloudFront failover.
- On the service detail page, click Actions.
- Select Pause.
- Confirm by clicking Pause in the dialog.
You should see a confirmation that the service is paused.
Why use "Pause" to simulate an outage?
Pausing is the safest way to simulate a regional failure. The service immediately stops responding (returns 404), but your configuration stays intact. You can resume it in seconds. In a real outage, the region might be completely unreachable - pausing gives us a controlled way to test the same scenario.
💡 What happens when an App Runner service is paused?
When you pause an App Runner service:
- The service stops running immediately and returns HTTP 404 for all requests
- No compute charges accrue while paused (you're not paying for idle resources)
- The service configuration, deployment settings, and custom domains are retained
- Resuming takes about 30-60 seconds to spin back up
Wait for CloudFront to Detect Failure
CloudFront health checks run continuously. When the primary returns errors, CloudFront routes to the secondary.
- Wait approximately 30 seconds for CloudFront to detect the failure.
- CloudFront caches health status, so give it time to recognize the change.
Test Failover
Now verify CloudFront has automatically switched to your secondary origin.
- Refresh your browser tab with the CloudFront URL.
- You should now see "Hello from us-west-2!" (or your secondary region's response).
✅ It's working
Great! CloudFront has automatically failed over to your secondary origin. Let's continue.
❌ Still seeing the primary region?
Still seeing the primary region's response?
If you still see "Hello from us-east-1":
- Not enough time: CloudFront caches the previous response. Wait another 30-60 seconds.
- Browser cache: Open an incognito/private browser window, or clear your browser cache completely.
- DNS cache: Some ISPs cache DNS aggressively. Wait a few more minutes.
- Edge propagation: The failover needs to propagate to all CloudFront edge locations. Give it up to 2 minutes.
Get help with failover testing or share your error with the NextWork community!
Verify in CloudFront Monitoring
You can also check CloudFront's monitoring to see the failover in action.
- Go back to CloudFront.
- Click on your distribution.
- Select the Monitoring tab.
- Look at the Origin error rate metrics - you should see errors from the primary origin.
Automatic failover happened at the edge in seconds - no DNS propagation delays, no manual intervention required.
Why is this faster than DNS failover?
Traditional DNS-based failover (using Route 53 health checks) requires DNS records to change and propagate globally - which can take minutes. CloudFront origin failover happens at the edge location level. When the edge server gets an error from the primary, it immediately retries with the secondary on the same request. Users experience a slightly slower response (two origin requests), but there's no propagation delay.
Resume the Primary Service
Let's bring the us-east-1 service back online.
- Navigate to App Runner.
- Ensure you're in the us-east-1 region.
- Click on your paused App Runner service.
- Click Actions.
- Select Resume.
- Confirm by clicking Resume in the dialog.
Wait for Service to Start
The App Runner service needs time to restart.
- Wait for the service status to change to Running.
- This typically takes 1-2 minutes.
- You can monitor the progress in the service's Activity tab.
Once the service is running, you'll see the status change.
Wait for CloudFront Health Check
Once the primary is healthy again, CloudFront will automatically prefer it.
- Wait approximately 30-60 seconds after the service is running.
- CloudFront needs time to detect the primary is healthy again.
How does CloudFront know when to fail back?
CloudFront doesn't have a "health check" in the traditional sense - it evaluates origin health based on the responses it receives. Once your primary origin starts returning successful responses (200 OK) instead of errors, CloudFront automatically prefers it again. This is called "passive health checking" - CloudFront learns from actual traffic rather than sending probes.
Test Failback
Verify CloudFront has returned to the primary origin.
- Refresh your browser tab with the CloudFront URL.
- You should now see "Hello from us-east-1!" again (your primary region's response).
✅ It's working
Great! CloudFront has automatically failed back to your primary origin. Your failover system is working.
❌ Still seeing the secondary region?
Still seeing the secondary region?
If you still see "Hello from us-west-2":
- Service not fully started: App Runner takes 30-60 seconds to become fully responsive. Check the service status shows "Running".
- Cache TTL: CloudFront may still be serving cached responses. Wait for the cache to expire (usually 1-2 minutes).
- Browser cache: Try an incognito/private browser window.
- Give it time: CloudFront prefers primaries that consistently succeed. Wait a full 2 minutes for it to build confidence.
Get help with failback testing or share your error with the NextWork community!
Review Failover Timeline in Monitoring
Let's analyze exactly when failover and failback occurred using CloudFront's built-in monitoring.
- Go to CloudFront.
- Click on your distribution.
- Select the Monitoring tab.
- Expand the time range to see the full test period.
- Look at the Requests and Error rate graphs.
You should see:
- Normal traffic to primary origin initially.
- Spike in errors when you paused the service.
- Traffic shifting to secondary origin.
- Traffic returning to primary after you resumed the service.
This monitoring data shows exactly how long failover took and when traffic returned to normal.
What should you see in the monitoring graphs?
The monitoring graphs tell the story of your failover test:
- Requests graph: Shows consistent traffic throughout the test
- Error rate spike: When you paused us-east-1, errors spiked briefly (the failed requests to the primary)
- Error rate drop: Once failover kicked in, errors dropped (successful requests to secondary)
- Return to normal: After resuming, traffic smoothly returned to the primary
If you see a clean pattern like this, your failover is working as designed!
Secret mission
Automatic failover is great - but how do you know it happened? DAZN's engineers don't wait for Twitter complaints during a Champions League match. They get instant alerts the moment something goes wrong.
By now, you've built automatic failover between two AWS regions. In this secret mission, you'll add the final piece of production-grade infrastructure: automated alerting. You'll set up CloudWatch alarms that notify you via email the instant CloudFront detects an origin failure - the same observability pattern used by teams serving billions of requests.
Build Production Alerting for Failover Events
Clean Up Your Resources
Clean Up Your Resources
Nice work completing this project! Choose how much you want to clean up based on your plans.
CloudFront Only
If you want to keep your App Runner services for future projects, just remove CloudFront:
1. Disable and delete CloudFront distribution:
- Go to CloudFront
- Select your distribution → Click Disable
- Wait for status to change to "Disabled" (takes a few minutes)
- Select the distribution again → Click Delete
Your App Runner services will continue running in both regions!
Remove Everything
If you're done with the entire disaster recovery series, here's how to clean up everything:
1. Disable and delete CloudFront distribution:
- Go to CloudFront
- Select your distribution → Click Disable
- Wait for status to change to "Disabled"
- Select the distribution again → Click Delete
2. Delete App Runner services:
- Go to App Runner in us-east-1
- Select your service → Actions → Delete
- Type the service name to confirm → Click Delete
- Switch to us-west-2 and repeat
3. Delete CloudWatch alarm (if created):
- Go to CloudWatch
- Click Alarms → All alarms
- Select your alarm → Actions → Delete
4. Delete SNS topic (if created):
- Go to SNS
- Click Topics → Select your topic → Delete
That's a wrap!
That's a wrap!
You did it! You've built an auto-failover system using CloudFront origin groups that eliminates manual intervention during outages.
What you learned:
- 🌐 How CloudFront origin groups enable automatic failover between regions
- ⚡ Why edge-level failover is faster than DNS-based failover - no propagation delays
- 🔧 How to configure failover criteria including 404 to catch paused services
- 🔄 How CloudFront automatically fails back when the primary origin recovers
- 📊 How to use CloudFront monitoring to track failover events
Ready to quiz yourself? 💪
What's next?
In Project #3 of this Disaster Recovery series (coming soon), get ready to add automated alerting with CloudWatch and SNS!
Make sure to join the NextWork Community to be the first to hear when it's out 🤝
p.s. Does it say "Still tasks to complete!" at the bottom of the screen?
This means you still have screenshots left to upload, or questions left to answer!
- Press Ctrl+F (Windows) or Command+F (Mac) on your keyboard.
- Search for the text Return to later.
- Jump straight to your incomplete tasks!
- 🙋♀️ Still stuck? Ask the community!