I see 4 solutions to this problem. The first 3 were already covered in answers and the last one is my contribution. 1. [Set the error document to index.html.](https://stackoverflow.com/a/16979716/1476885) **Problem**: the response body will be correct, but the status code will be 404, which hurts SEO. 2. [Set the redirection rules.](https://stackoverflow.com/a/16877231/1476885) **Problem**: URL polluted with `#!` and page flashes when loaded. 3. [Configure CloudFront.](https://stackoverflow.com/a/35354677/1476885) **Problem**: all pages will return 404 from origin, so you need to chose if you won't cache anything (TTL 0 as suggested) or if you will cache and have issues when updating the site. 4. Prerender all pages. **Problem**: additional work to prerender pages, specially when the pages changes frequently. For example, a news website. My suggestion is to use option 4. If you prerender all pages, there will be no 404 errors for expected pages. The page will load fine and the framework will take control and act normally as a SPA. You can also set the error document to display a generic error.html page and a redirection rule to redirect 404 errors to a 404.html page (without the hashbang). Regarding 403 Forbidden errors, I don't let them happen at all. In my application, I consider that *all* files within the host bucket are public and I set this with the *everyone* option with the *read* permission. If your site have pages that are private, letting the user to see the HTML *layout* should not be an issue. What you need to protect is the *data* and this is done in the backend. Also, if you have private assets, like user photos, you can save them in *another* bucket. Because private assets need the same care as *data* and can't be compared to the asset files that are used to host the app.