A Non-Embarrassing 404 Page: Helpful Links, Search, Lightweight Humor

Was this helpful?

You shipped a new marketing page, somebody pasted the link into Slack, and now every click lands on a dead end. Not a graceful dead end. The default web server 404 with a cold “Not Found,” like a locked door with no sign and no handle.

This is the small stuff that costs real money: users bounce, support tickets pile up, search engines get confused, and your on-call gets paged because a 404 spike looks exactly like an outage. A good 404 page is not “cute.” It’s incident prevention with a UX wrapper.

What a 404 page is really for (and what it’s not)

A 404 page is customer support, navigation, and telemetry in one response. Treat it like an operational surface, not decorative error art.

When someone hits a missing URL, they’re telling you one of four things:

  • They followed a broken link (internal, external, or stale cache).
  • They typed something close (human error, autocomplete, or “I swear it used to exist”).
  • A bot is probing (normal crawlers, security scanners, opportunistic nonsense).
  • Your routing or deploy is wrong (misconfigured rewrite rules, missing assets, partial rollout, bad CDN behavior).

The job of the 404 is to sort those cases quickly: recover the user if possible, and give you enough data to fix the root cause. What it should not do is pretend everything is fine. Returning a 200 with an error message is an SEO and caching footgun, and it makes troubleshooting harder because “success” in metrics hides failure in reality.

There’s also a social contract here. A user landing on a 404 is slightly embarrassed, even if it’s your fault. Don’t amplify that with a passive-aggressive tone. Be direct, be helpful, and move them forward.

Facts and history that still matter in 2025

These aren’t trivia for trivia’s sake. Each point explains why certain 404 choices are still surprisingly consequential.

  1. HTTP 404 is defined as “Not Found,” meaning the server has no current representation for the target resource. That “current” wording matters: it doesn’t claim the resource never existed, just that it’s not available now.
  2. 410 Gone is different. 410 is an explicit statement that the resource is intentionally and permanently removed. Search engines typically drop 410 URLs faster than 404 URLs.
  3. Search engines coined “soft 404” to describe pages that look like errors but return 200 OK, or redirect everything to the homepage. Those can harm trust and indexing quality.
  4. Early web servers shipped with bare error pages because bandwidth and CPU were expensive and dynamic templates were less common. That legacy still shapes defaults: many stacks still send minimal HTML for 404s unless you override.
  5. CDNs popularized edge-cached error handling. A 404 can be cached at the edge just like a 200, and that can be either your best friend (performance) or your worst enemy (stale missing pages after a deploy).
  6. Browsers and proxies treat 404 differently than 200. For example, caches may store 404s with different heuristics, and client code often checks status codes to branch logic.
  7. Security scanners love 404 surfaces. Many exploit chains start with discovery: requests for common admin paths, old plugin endpoints, or misconfigured backups. Your 404 response headers and timing can leak stack details if you’re sloppy.
  8. SPAs made 404 routing confusing. Client-side routers often want “serve index.html for unknown paths,” which is correct for app routes but wrong for actual missing content. The distinction matters for SEO and user clarity.
  9. Historically, a broken link was “somebody else’s problem.” Today, analytics and search console tooling make it measurable, so ignoring 404s is a choice—usually a bad one.

Design principles: make the 404 do work

1) Confirm what happened, without drama

State the truth in plain words: “We can’t find that page.” Then provide a few next actions. Don’t blame the user. Don’t imply the site is broken unless it is. A 404 is often a single missing URL, not an outage.

2) Give two or three high-quality exits

A good 404 page is intentionally small. You’re not rebuilding navigation; you’re offering escape hatches:

  • Home (yes, but don’t rely on it alone).
  • Search (the best universal recovery tool).
  • Top tasks for your product (pricing, docs, status, contact, login—choose what your users actually do).

Keep it to 5–8 links. Too many links become a visual shrug, and users bounce anyway.

3) Preserve context when you can

If you know where the user came from, use it. “Go back” isn’t a link; it’s a browser function, and users know it exists. Give them a real link: “Return to previous page” (referrer-based), or show “You may have meant…” suggestions derived from the missing path.

One simple trick that works: parse the URL path segments and offer a broader parent path if it exists (e.g., /docs/storage/… → /docs/storage/).

4) Don’t leak internals

Your 404 page is viewed by everyone, including bots that collect your mistakes. Avoid:

  • Framework/version strings in headers or HTML.
  • Stack traces, debug IDs that map to internal systems, or raw exception messages.
  • Echoing untrusted URL content into the page without escaping.

5) Make the page cheap to serve

404s are bursty. When something breaks—a popular blog link, a product rename, a deploy removing an endpoint—your 404 rate can spike 10–100×. If your 404 page depends on slow backend calls or heavyweight client bundles, it turns a content error into an availability incident.

6) Instrument it like a production endpoint

You want to know:

  • Which missing URLs are hottest.
  • Referrers generating the broken traffic.
  • User agents that indicate scanners vs humans.
  • Whether the 404s correlate with deploys, CDN changes, or DNS shifts.

Copy and humor: one eyebrow raise, not a comedy set

Write copy the way you’d write an incident update: calm, clear, and oriented toward next steps.

Do: “That page isn’t here. Try search or head to Pricing.”

Don’t: “Oopsie! Something went wrong!!!” (It didn’t. A link is missing.)

Humor is allowed, but it must be lightweight and optional—like seasoning. If the user is stuck, jokes feel like you’re laughing at them. If the user can recover quickly, a small chuckle is fine.

Joke #1: The page you asked for is on a coffee break and didn’t leave a forwarding address.

Notice what that joke doesn’t do: it doesn’t mock the user, it doesn’t mention “server errors,” and it doesn’t imply the site is unstable. It’s a tiny human moment, then back to business.

Joke #2: We looked everywhere—even under the cache—but this URL still isn’t real.

Two jokes. That’s enough. If you need more humor than that, what you actually need is better IA, redirects, and link hygiene.

HTTP semantics and SEO: avoid “soft 404” traps

Here’s the opinionated rule: return 404 for content that does not exist. Do not redirect everything to the homepage. Do not return 200 with a friendly message. That’s how you end up with a search index full of garbage and a monitoring system full of lies.

Status code choices

  • 404 Not Found: default for missing pages or resources.
  • 410 Gone: use for permanently removed content when you’re sure it’s not coming back.
  • 301 Moved Permanently: use when there is a clear replacement URL. Do not 301 to “kind of similar.”
  • 302/307: for temporary moves during migrations or experiments.

Canonical and indexing guidance

A 404 page shouldn’t be indexed as content. Usually you’ll:

  • Return a true 404 status.
  • Include noindex meta (belt and suspenders; the status already tells most crawlers what to do).
  • Avoid canonical tags pointing to real pages unless you’re doing something very deliberate.

Why “redirect to homepage” is a bad habit

It feels helpful. It’s not. It hides broken links, confuses analytics funnels, and teaches crawlers that your site doesn’t respect URL meaning. Users also hate it: they clicked a specific page and got thrown into the lobby with no directions.

Single-page apps: split “unknown route” from “missing content”

SPAs often serve index.html for any path so the client router can render the right view. That’s fine for valid client routes. But when the route truly doesn’t exist, you still want a 404—not a 200 with a “page not found” component.

Practical approach: keep a server-side route allowlist for SPA paths, or have the application return 404 at the API level for unknown content and have the server return 404 for unknown asset paths.

Logging, monitoring, and alerting: 404s as signals

404s are not always “errors” in the operational sense. Bots will probe. Old links will exist. But spikes and patterns are actionable, and if you ignore them you’ll spend more time later doing forensic archaeology.

What to log for a 404

  • Requested path and query string (with privacy guardrails).
  • Referrer.
  • User agent (or a hashed/parsed classification).
  • Host header (multi-tenant sites matter here).
  • Response time and upstream time (should be near-zero upstream for a good 404).
  • Cache status (HIT/MISS/BYPASS) if behind a CDN or reverse proxy.

What to alert on

Alert on rate changes, not absolute values. A site with lots of long-tail content will always have some 404s.

  • 404 rate spike relative to baseline.
  • Top 404 URL suddenly hot (often indicates a broken internal link or a marketing campaign typo).
  • 404s for static assets (can indicate broken deploy, missing build artifacts, or CDN purge issues).
  • High 404 + high latency (your 404 handler is doing too much work).

Privacy and compliance reality

Don’t casually log personal data. Query strings often include emails, tokens, or search terms. You can still be useful while being careful:

  • Strip or hash known sensitive parameters.
  • Keep short retention for raw logs; keep aggregated metrics longer.
  • Classify user agents instead of storing full strings if you can.

Performance and reliability: your 404 is on the hot path

Most teams think about performance on the homepage and key product flows. Meanwhile, 404s quietly become a denial-of-wallet vector because they’re easy to trigger and often poorly cached.

Keep the payload small

A 404 page should be mostly HTML and a sprinkle of CSS. If you ship a massive JS bundle to tell the user “not found,” you deserve the bill you get.

Cache strategically

Caching 404s is useful but nuanced:

  • Cache 404 responses for obvious bot probes (e.g., common exploit paths) for a short TTL, at the edge if possible.
  • Be cautious caching 404 for “maybe newly deployed” content. If you cache a 404 for a URL that will exist after the next deploy, you create self-inflicted “it works in origin but not at the edge” incidents.
  • Use different TTLs by path prefix. Static asset 404s can be cached longer; dynamic content paths might need shorter TTLs.

Make it resilient to backend outages

One of my favorite quiet wins is serving 404s entirely from the reverse proxy layer, with no app dependency. When the app is down, the proxy can still respond correctly to missing paths and avoid tying up upstream queues.

Fast diagnosis playbook

This is the “I have 15 minutes and an impatient stakeholder” workflow. The goal is to identify whether the bottleneck is content, routing, caching, or deployment.

First: confirm status codes and scope

  • Is it a true 404 from the origin, or a 404 from the CDN/WAF, or a 200 with “not found” content?
  • Is it one URL or a whole prefix?
  • Is it only one region/POP, or everywhere?

Second: find the referrer and the source of truth

  • Internal link? Fix it immediately and ship.
  • External link? Add a redirect if it’s popular and the destination is obvious.
  • Bot noise? Rate-limit or cache it; don’t panic.

Third: check deployment and routing changes

  • Did a rewrite rule change?
  • Did an SPA fallback rule accidentally swallow real 404s?
  • Did the build stop publishing assets (hash mismatch, artifact missing)?

Fourth: check caching behavior

  • Is the CDN caching 404s too aggressively?
  • Is the origin sending cache headers you didn’t intend?
  • Is there a stale edge config?

Fifth: validate the 404 page itself

  • Is the 404 handler slow or calling upstream services?
  • Is it generating errors (500) under load?
  • Is it loading heavy JS/CSS from missing asset URLs (404 inside 404)?

Hands-on tasks: commands, outputs, and decisions

These tasks are designed for real production debugging. Each includes a command, a representative output, what it means, and the decision you make next.

Task 1: Verify the status code is a real 404 (not a soft 404)

cr0x@server:~$ curl -s -D- -o /dev/null https://www.example.com/definitely-missing-page
HTTP/2 404
date: Mon, 29 Dec 2025 10:15:21 GMT
content-type: text/html; charset=utf-8
cache-control: max-age=60

What it means: The server returns an actual 404. Good start. Cache-Control indicates it may be cached for 60 seconds.

Decision: If users report “it exists but I get 404,” suspect caching or rollout. If it’s truly missing, move to referrer analysis.

Task 2: Detect a soft 404 (200 with “not found” content)

cr0x@server:~$ curl -s -D- https://www.example.com/definitely-missing-page | head -n 12
HTTP/2 200
date: Mon, 29 Dec 2025 10:16:02 GMT
content-type: text/html; charset=utf-8

<!doctype html>
<html>
<title>Page not found</title>

What it means: This is a soft 404. Your monitoring, caching, and SEO will all get worse.

Decision: Fix routing so missing content returns 404. For SPAs, implement server-side allowlist or proper status handling.

Task 3: Check whether the CDN is the one returning the 404

cr0x@server:~$ curl -s -D- -o /dev/null https://www.example.com/definitely-missing-page | egrep -i 'server:|via:|x-cache:|cf-cache-status:|x-served-by:'
server: cloudflare
cf-cache-status: HIT

What it means: The response is served by the CDN and cached (HIT). The origin might not be involved.

Decision: If the page recently started existing, purge or lower TTL for 404s on that path. If it’s truly missing, consider caching longer for bot-heavy paths.

Task 4: Confirm origin behavior by bypassing the CDN (where possible)

cr0x@server:~$ curl -s -D- -o /dev/null --resolve www.example.com:443:203.0.113.10 https://www.example.com/definitely-missing-page
HTTP/2 404
date: Mon, 29 Dec 2025 10:18:12 GMT
server: nginx

What it means: Direct-to-origin also returns 404, so the CDN isn’t inventing the error.

Decision: Treat it as missing content or origin routing misconfig. Move to logs to see referrers and patterns.

Task 5: Find top 404 paths in NGINX access logs

cr0x@server:~$ awk '$9==404 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head
  842 /wp-login.php
  311 /docs/storage/zfs-tuning
  207 /assets/app.8f3c1d.js
   98 /favicon.ico

What it means: You have both bot probes (/wp-login.php) and a likely real broken link (/docs/storage/zfs-tuning) plus a missing asset.

Decision: Bot probe: short-cache and/or WAF rule. Docs link: add redirect or fix internal links. Missing asset: treat as a deploy/CDN issue immediately.

Task 6: Identify who is sending users to the missing URL (referrer analysis)

cr0x@server:~$ awk '$9==404 {print $11}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head
  126 "https://www.example.com/docs/storage/"
   88 "https://www.example.com/blog/introducing-zfs"
   41 "-"

What it means: A docs page and a blog post are linking to missing targets. “-” indicates no referrer (typed/bookmarked/bot).

Decision: Fix the source pages first. Redirects help, but correcting internal links prevents repeated 404s.

Task 7: Confirm whether the missing asset exists on disk (static build sanity)

cr0x@server:~$ ls -lh /var/www/html/assets/ | head
total 12M
-rw-r--r-- 1 www-data www-data  92K Dec 29 09:57 app.91a2ce.js
-rw-r--r-- 1 www-data www-data  31K Dec 29 09:57 app.91a2ce.css

What it means: The asset referenced in logs (app.8f3c1d.js) isn’t present; a different hash exists. Likely an HTML referencing a stale build or a partial deploy.

Decision: Check deploy artifacts and ensure HTML and assets are deployed atomically. If using a CDN, purge old HTML or adjust caching to avoid serving mismatched bundles.

Task 8: Check NGINX config for 404 handling and SPA fallbacks

cr0x@server:~$ sudo nginx -T 2>/dev/null | egrep -n 'error_page|try_files|location /' | head -n 20
45:    error_page 404 /404.html;
78:    location / {
79:        try_files $uri $uri/ /index.html;
80:    }

What it means: The server uses try_files to fall back to /index.html. That’s fine for SPA routes, but it can create soft 404s if index.html returns 200 for missing routes.

Decision: Ensure SPA router returns proper 404 for unknown client routes, or implement a server-side distinction for known SPA paths vs unknown.

Task 9: Validate the 404 page is lightweight (TTFB and size)

cr0x@server:~$ curl -s -o /dev/null -w "status=%{http_code} ttfb=%{time_starttransfer} size=%{size_download}\n" https://www.example.com/definitely-missing-page
status=404 ttfb=0.038241 size=6142

What it means: Fast TTFB and small payload. That’s what you want.

Decision: If TTFB is high, the 404 path is doing backend work. Fix by serving a static 404 at the edge/proxy.

Task 10: Verify cache headers for 404 responses

cr0x@server:~$ curl -s -D- -o /dev/null https://www.example.com/definitely-missing-page | egrep -i 'cache-control|expires|age'
cache-control: public, max-age=3600
age: 2540

What it means: The 404 is cached for an hour and has already been cached for 42 minutes. That can be correct for bot probes, dangerous for newly published content.

Decision: Reduce TTL for content-like paths, keep longer TTL for obvious junk paths. Split by location block or CDN rules.

Task 11: Check whether redirects exist for known legacy paths

cr0x@server:~$ curl -s -D- -o /dev/null https://www.example.com/docs/storage/zfs-tuning | head -n 8
HTTP/2 404
date: Mon, 29 Dec 2025 10:24:19 GMT

What it means: No redirect. If this is a common miss (from Task 5), you’re bleeding users.

Decision: Add a 301 to the best replacement, or restore the page if it was removed accidentally. If it was intentionally removed, consider 410.

Task 12: Identify whether 404s correlate with deploy time

cr0x@server:~$ journalctl -u nginx --since "2025-12-29 09:30" --until "2025-12-29 10:30" | egrep -i 'reload|signal|start'
Dec 29 09:58:01 web-1 nginx[1321]: signal process started
Dec 29 09:58:02 web-1 nginx[1321]: signal process started

What it means: NGINX reload happened around the time assets changed. Combined with missing asset hash, this suggests a deployment issue.

Decision: Inspect deployment pipeline for atomicity; verify that the HTML references the correct asset hash and caches are purged coherently.

Task 13: Spot a 404 storm driven by a single bot UA

cr0x@server:~$ awk '$9==404 {print $12,$7}' /var/log/nginx/access.log | head -n 3
"Mozilla/5.0" /wp-login.php
"SomeScanner/1.2" /admin.php
"SomeScanner/1.2" /.git/config

What it means: A scanner is probing predictable paths. These should be cheap to serve and ideally blocked or tarpitted at the edge.

Decision: Add WAF rules or NGINX rate limiting for abusive patterns. Cache these 404s longer with a minimal body to save origin resources.

Task 14: Confirm the 404 page isn’t itself causing more 404s (missing CSS/JS)

cr0x@server:~$ curl -s https://www.example.com/404.html | egrep -o 'href="[^"]+|src="[^"]+' | head
href="/assets/app.8f3c1d.css
src="/assets/app.8f3c1d.js

What it means: Your 404 page depends on assets that might be missing (as seen earlier). That creates a second failure mode: “404 page renders broken,” and it generates more 404 noise.

Decision: Inline minimal CSS for the 404 page or reference stable, versioned assets that you guarantee exist. Keep it independent of your main app bundle.

Three corporate mini-stories (anonymized, painfully plausible)

Mini-story 1: The incident caused by a wrong assumption

The company was mid-rebrand, which meant URLs were changing. A product manager asked for “no broken links,” and someone translated that into “redirect all unknown paths to the homepage.” It sounded customer-friendly and it made the 404 graph go quiet. Everyone took the quiet as success.

Two weeks later, paid search conversions dipped. Not crashed—just sagged. The marketing team blamed ad targeting. The web team blamed tracking. Analytics showed healthy traffic and a suspiciously low 404 rate, which looked like evidence against “broken links.”

The real problem: users were landing on deep links from ads and old content, getting 302’d to the homepage, and then leaving. Sessions looked “successful” in basic dashboards because the homepage was a 200. The funnel looked broken because the landing page intent was destroyed.

When the SRE on-call finally pulled raw logs, it was obvious: a small set of old high-intent URLs were being redirected to “/” at high volume. Fixing it was boring: implement specific 301 redirects to the correct new pages, restore real 404s for unknown URLs, and add monitoring for redirect-to-home anomalies.

The wrong assumption was that “users hate 404s, so eliminate 404s.” Users hate dead ends. A truthful 404 with a search box is better than lying with a homepage redirect.

Mini-story 2: The optimization that backfired

A team wanted to reduce origin load. They decided to edge-cache 404s aggressively: Cache-Control: public, max-age=86400 for everything that returned 404. It worked immediately for bot noise and random probes. Origin request volume dropped. Someone declared victory.

Then a partner published a high-traffic link to a page that didn’t exist yet, because the launch schedule shifted by a day. During the first wave of traffic, the page correctly returned 404. The CDN cached it for a day. When the page went live a few hours later, users still got 404 from the edge.

The incident was brutal because it looked like “the page is deployed but still missing.” Origin tests passed. Only some regions were affected. Purges were issued, but propagation wasn’t instantaneous, and not all caches were cleared consistently.

The postmortem outcome was not “never cache 404.” It was “cache 404s with intent.” They introduced path-based TTLs: short TTL for content-like paths that might appear, long TTL for obvious exploit probes, and immediate bypass for certain launch-critical prefixes during releases.

Optimization is not a synonym for “set a long TTL.” Optimization is choosing what you can afford to be wrong about.

Mini-story 3: The boring but correct practice that saved the day

A different company had a rule that sounded unglamorous: every 404 must include an internal request ID, and the top 20 404 paths must be reviewed weekly. Not “when we have time.” Weekly. The review rotated between the web team and support.

One Monday, the report showed a new hot 404: a path under the billing section. The referrer was internal: a link in an onboarding email template. Nobody had touched the billing app. The email template was managed by marketing.

Because the 404 page included the request ID and the logs were structured, they traced it in minutes. The URL was missing a hyphen—an easy human typo. The fix was also boring: update the email template and add a redirect from the wrong URL to the right one for safety.

The best part: this never became a “site outage.” It stayed a low-grade operational paper cut that got cleaned up before it bled. No blame. No drama. Just a small weekly habit paying dividends.

Boring processes are underrated. The trick is picking boring processes that actually connect to user pain.

Common mistakes: symptoms → root cause → fix

1) Symptom: “Our 404 page shows up in Google results”

Root cause: Soft 404 (status 200), or incorrect canonical/noindex handling, or a CDN rewriting status codes.

Fix: Return true 404 for missing pages. Add noindex meta on the 404 template. Verify with curl -D- that status is 404 end-to-end (CDN included).

2) Symptom: “Users see the homepage when they click old links”

Root cause: Catch-all redirect rule for unknown paths.

Fix: Remove catch-all redirects. Add targeted 301 redirects for known legacy URLs and keep true 404 for unknown URLs.

3) Symptom: “404 spike after deploy, mostly assets”

Root cause: Non-atomic deploy of HTML + hashed assets; stale HTML cached longer than assets; incorrect purge order.

Fix: Deploy assets first, then HTML, or deploy to versioned directories and switch a pointer atomically. Align caching: short TTL for HTML, long TTL for immutable hashed assets.

4) Symptom: “404 page is slow and triggers timeouts under load”

Root cause: 404 handler calls application services (search, personalization, experiments), or renders via heavy server-side templates.

Fix: Serve a static 404 page at the proxy/edge. Keep it independent of upstream dependencies. Timebox any optional calls and fail closed to static.

5) Symptom: “We can’t reproduce the 404; users in one region can”

Root cause: CDN caching of 404s, inconsistent purges, or split deployments.

Fix: Check cache headers and cache status. Bypass CDN to test origin. Purge specific URLs, then adjust 404 TTL by path.

6) Symptom: “Support gets spammed with broken link reports”

Root cause: Report link lacks friction and routing; bots trigger it; users use it as general feedback.

Fix: Add basic abuse controls (rate limit, CAPTCHA only if necessary), include structured fields, and route into triage with clear category selection.

7) Symptom: “Security team complains the 404 page leaks stack details”

Root cause: Default server signatures, framework headers, debug output, or reflected input.

Fix: Remove/override server tokens, disable debug, escape all reflected strings, and ensure error templates don’t include environment details.

8) Symptom: “Monitoring doesn’t show the issue; users complain anyway”

Root cause: Soft 404s counted as success, or dashboards only track 5xx, or redirects hide errors.

Fix: Track 404 and 3xx rates separately. Alert on changes. Log referrers. Monitor top missing paths.

Checklists / step-by-step plan

Checklist A: Build a 404 page that helps users recover

  1. Write clear copy: “We can’t find that page.” No blame, no panic.
  2. Add a search box that submits to a dedicated search endpoint (don’t auto-call search on render).
  3. Curate 5–8 links to top tasks. Keep it tight.
  4. Offer context: show the requested path, safely escaped, and a “go back” link if referrer exists.
  5. Add a report option only if you can triage it. Pre-fill missing URL and referrer.
  6. Make it accessible: proper headings, focus management, and readable contrast.

Checklist B: Make it correct for SEO and caching

  1. Return HTTP 404 for missing resources. Validate at the edge.
  2. Use 410 selectively for intentionally removed pages that won’t return.
  3. Add noindex to the 404 template.
  4. Do not redirect unknown URLs to homepage. Use targeted redirects only.
  5. Set sane cache headers: short TTL for content-like 404s, longer TTL for obvious bot probes.

Checklist C: Instrumentation and operations

  1. Log 404s with structure: path, status, referrer, UA class, request ID, cache status.
  2. Create a top-404 report (daily or weekly) and assign ownership.
  3. Alert on spikes, not on existence. 404s are normal; sudden changes aren’t.
  4. Track asset 404s separately from page 404s.
  5. Run a broken internal link check as part of CI for docs/content.

Checklist D: Migration and redesign safety

  1. Inventory high-traffic URLs before changing information architecture.
  2. Plan redirects for the obvious replacements; avoid “close enough” redirects.
  3. Keep old URLs alive for a period with 301s, especially for docs and blog posts.
  4. Re-test after CDN changes: status codes, caching, and purge behavior.

FAQ

Should a 404 page return 404 or 200?

Return 404. A 200 with “not found” content is a soft 404 that breaks SEO signals, analytics accuracy, and operational visibility.

When should we use 410 Gone instead of 404?

Use 410 when you are confident the content is intentionally removed and not returning. It’s a stronger signal for crawlers and helps reduce repeated crawling of dead URLs.

Is it okay to redirect missing pages to the homepage?

No, not as a blanket rule. It hides broken links and harms user intent. Use targeted redirects only when there’s an actual replacement.

Should the 404 page include a site-wide navigation menu?

Usually no. Provide a small set of high-value links instead. Full navigation encourages “wander until you give up,” and it increases page weight.

Do we need a search box on the 404 page?

If you have more than a handful of pages, yes. It’s the fastest recovery tool. But don’t make the 404 render depend on a search backend call.

How do we prevent bots from causing expensive 404 responses?

Serve 404s cheaply, cache obvious probe paths, and rate-limit abusive patterns. Keep your 404 handler static and avoid backend dependencies.

Why do we see a lot of 404s for /wp-login.php when we don’t run WordPress?

That’s common background noise from scanners. Treat it as an opportunity to save money: return a minimal cached 404 and consider WAF rules.

How do we tell if the CDN is caching 404s incorrectly?

Check headers like Age and CDN cache status. Compare edge vs origin behavior by bypassing the CDN (when possible) and reviewing cache-control policy by path.

Our SPA always serves index.html. How do we handle 404 correctly?

Keep SPA fallback only for known app routes. Unknown paths should return 404 at the server, or the client router must render a 404 view while the server still returns a 404 status where feasible.

Should we include a “report broken link” button?

Only if you can triage it reliably and defend it from abuse. If you add it, pre-fill missing URL + referrer and route into a queue that gets reviewed.

Conclusion: practical next steps

A non-embarrassing 404 page is not a branding exercise. It’s a small reliability feature that keeps users moving and keeps your team informed. Done well, it reduces support load, protects SEO, and turns “missing” into “actionable.”

Do this next, in order:

  1. Make status codes truthful: kill soft 404s and catch-all homepage redirects.
  2. Make the 404 cheap: static response, minimal assets, no backend calls required.
  3. Add recovery tools: a search box (submit-based) and a short list of top-task links.
  4. Instrument and review: log referrers, track top missing URLs, and set spike alerts.
  5. Fix the sources: internal broken links first, then targeted redirects for popular external misses.

If you do only one thing: stop treating 404 as a dead end. It’s a diagnostic endpoint with a user standing in front of it.

← Previous
ZFS ARC sizing: When Too Much Cache Slows Down Everything Else
Next →
WordPress Thumbnail Issues: Regenerate Thumbnails Without Taking the Site Down

Leave a comment