3am, prod went down for four minutes. The gateway returned nginx's default page — "502 Bad Gateway" in white-on-black, no logo, nothing. Someone screenshotted it and posted: "KB Labs production, very polished."
Fixed by morning. But 1,200 people had already seen the screenshot.
A 500 page isn't cosmetics you get to "when there's time." It's the last thing someone sees before closing the tab. And possibly before writing something about you somewhere public.
Who actually sees 5xx
Think about who this might be:
- A user who just clicked something and didn't get an answer.
- A customer with a deadline in an hour who's pulling data through your API.
- A journalist who landed on your site for the first time from a tweet.
- An engineer who is right now deciding whether to recommend you to their team.
All of them, in that moment, are one click away from leaving. If they see a default nginx "Internal Server Error 500" instead of something real — the signal is clear: "nobody thought about this."
And they leave.
What should be there
You don't need to design something beautiful. You need it to be obvious that you thought about this moment.
Brand. Logo, colors, typeface. The person needs to understand it's your site that's down, not the internet.
Normal text. Not Internal Server Error 500. Something like:
Something broke on our side. We already know and we're fixing it. Try again in a minute.
No jargon. If you know what specifically broke — say it directly.
Request ID. A short identifier they can copy and send to support. Turns "I can't do anything" into "here's my ID, please help." The user stops feeling like a victim.
What shouldn't be there. Stack traces, framework names, X-Powered-By headers. That's both a security risk and a signal that you don't control what you return.
For API clients. If the request has Accept: application/json — return JSON, not HTML. HTML in a JSON parser creates a second bug on top of the first. Clean JSON with the same fields — five lines of nginx config.
This is a one-time job
One HTML file, one JSON fallback, ~30 lines of nginx config with proxy_intercept_errors on and error_page 500 502 503 504 = @handler. Done. After that your whole infrastructure — gateway, web, docs, anything added later — automatically returns a real page on any upstream failure.
Once. Then you never think about it again.
Why it's easy to put off
It doesn't ship features, it doesn't move metrics. Easy to throw in the backlog.
But every time prod goes down and your error page is a default nginx screen, you're making it worse for yourself at the exact moment when things are already bad.
One day of work. Then it's done.