- Newest
- Most votes
- Most comments
I cannot replicate your issue. You CloudFront link loads just fine with almost every elements with status code - 200.
A consistent 503 LimitExceeded from CloudFront almost always points to throttling at the S3 origin rather than CloudFront itself. When CloudFront uses an S3 bucket configured as a static website endpoint (the one ending in s3-website-...amazonaws.com), it communicates through the public website layer, which has much lower request concurrency limits. It’s better to set your CloudFront origin to the bucket’s REST API endpoint (mlem-website.s3.us-east-1.amazonaws.com) instead of the website endpoint.
—Taz
answered 10 months ago
That's interesting, all of the guides and the AWS UI seem to push developers in the direction of creating a public static website first, and linking to that via CloudFront. I'll make the change, thanks!
The 503 LimitExceeded errors you're experiencing are likely related to Amazon S3 request rate limits. When using S3 as an origin for CloudFront, S3 has specific request rate limits per prefix. For a single prefix, S3 can handle 3,500 PUT/COPY/POST/DELETE or 5,500 GET/HEAD requests per second.
Even though you're the only user testing the site, if your static website has many resources (images, CSS, JavaScript files, etc.) that are all stored under the same prefix in your S3 bucket, CloudFront might be sending too many requests to that prefix simultaneously when loading the page.
Here are some solutions to try:
-
Distribute your objects across multiple prefixes in your S3 bucket. For example, instead of storing all files at the root level, organize them into folders like /images/, /css/, /js/, etc. This allows S3 to scale up to handle requests for each prefix separately.
-
Ensure your CloudFront distribution is properly caching content. Since you mentioned you've set the Cache Policy to "CachingDisabled," CloudFront is forwarding every request to your origin. Change this back to "CachingOptimized" to reduce the number of requests hitting your S3 bucket.
-
If you're using the S3 website endpoint as your origin, consider switching to the S3 REST API endpoint with Origin Access Control (OAC) instead. This is the recommended approach for serving S3 content through CloudFront and may handle the request patterns differently.
-
Implement a gradual loading strategy for your website resources to avoid sending too many simultaneous requests to the same S3 prefix.
The fact that the site works when accessing it directly through S3 but fails through CloudFront suggests that CloudFront might be sending requests to S3 in a more concentrated burst than when you access the site directly, potentially hitting the S3 rate limits.
Sources
HTTP 503 status code (Service Unavailable) - Amazon CloudFront
Access Denied for CloudFront to S3 static site | AWS re:Post
Original Poster here! I went through a lot of testing, but I diagnosed that the CloudFront free-tier has burst limit to the number of simultaneous HTTP requests you can make before you start getting 503 errors.
There's no perfect solution to this, my best advice is to change to another plan entirely, I had success eliminating this issue when testing a pay-as-you go distribution.
However I did try to make the free-tier distribution work, I figured I could put in a queue system to my fetch() commands and limit their speed to avoid the limitations, and then add a retry system if I do catch a 503 error, so here's what I tried.
- Created a request-manager.js utility script to queue my fetch() requests on my website
- Exposed two variables that are accessible via URL parameters
- 'request-limit' sets the number of simultaneous request. Defaults to '999'
- 'request-delay' sets a time delay between the batches of requests in milliseconds (1000 == 1 second). Defaults to '0' for no delay
In testing, if I set my 'request-limit' to '10' and my 'request-delay' to '100', that seems to be good enough to not trigger the burst limit.
https://d3n5jstxb8npc3.cloudfront.net/?request-limit=10&request-delay=100
In addition I implemented a retry system into my queue system, but even though 503 errors are logged in the console, I can't catch them in my fetch() responses, because they appear as 200 'ok' status by the time my Javascript reads the response.
I also have another distribution for testing, using the pay-as-you-go plan. It works 100% correct without setting any arbitrary limits to my fetch() commands.
https://d2054d2g70vrs.cloudfront.net/
If anyone knows of a way to lift this limitation in the free-tier, please let me know! Also if this isn't going to change, I heavily recommend AWS acknowledge this limitation and add it to their documentation so future engineers can avoid this bug-hunt in the future.
answered 10 months ago

Coming back to the CloudFront distribution to test it this morning, and now everything loads. I'm curious what was going on yesterday, but at least it's behaving now.
CloudFront Distribution: https://d3n5jstxb8npc3.cloudfront.net/
I'm now able to replicate the issue again, after calling a CloudFront distribution invalidation (/*). Same 503 LimitExceeded error appears across a myriad of asset loads. The errors seem to stick around for an indeterminate amount of time (at least 1-2 hours, yesterday I had to wait all night for the issue to clear)
Right now I run a Github Action to copy my assets to my private S3 bucket and invalidate the CloudFront distribution whenever I update my main branch of my website repo. This seems to be a normal way of doing things, but this 503 CloudFront bug is actively blocking me from going live.