Home › CDN Operations › Custom Error Pages
CDN Operations

CDN Custom Error Pages: Designing Branded 404, 502, and 503 Pages

Alex Petrov — DevOps & Infrastructure Engineer Sep 13, 2026 9 min read

Default CDN error pages break trust. A stark white “502 Bad Gateway” or “Error 503: Service Unavailable” tells users your infrastructure failed — and tells attackers exactly what stack you run. Branded, edge-served error pages keep users oriented, preserve SEO equity, and maintain availability even when your origin is completely down.

This guide covers how to design, build, and deploy custom 404, 502, and 503 pages at the CDN edge — with performance budgets, failover logic, and production-ready configuration examples.

Core principle: Your error page must never depend on the system that just failed. If the origin is down, the error page assets — HTML, CSS, logos, and fonts — must be served entirely from the CDN edge cache or edge KV storage.

Why Error Pages Must Live at the Edge

When you rely on how CDN works in a standard reverse-proxy setup, most error responses still traverse the origin. That works for a 404 where the origin is healthy and simply reports “not found.” It fails catastrophically for 502 (Bad Gateway) and 503 (Service Unavailable), where the origin is unreachable, overloaded, or failing health checks.

Without edge-generated errors, users see one of three bad outcomes:

Branded edge error pages solve this by intercepting error status codes at the PoP and returning a fully self-contained response. They load in <100ms, work during regional origin outages, and keep users inside your conversion funnel instead of bouncing back to Google.

For observability, pair custom pages with proper CDN monitoring and observability — log every 5xx interception with PoP, cache status, and origin latency so you can distinguish edge issues from origin saturation.

404 vs 502 vs 503: Different Failures, Different UX

Not all errors deserve the same design. Users interpret them differently, and search engines treat them very differently.

Performance Comparison: Edge vs Origin Processing
Metric Edge Processing Origin Processing Improvement
Latency (p50)8–15 ms120–300 ms15–20x faster
Cache Hit Ratio85–95%N/AReduces origin load
TLS Handshake1–5 ms (nearby PoP)50–150 ms10–30x faster
Bandwidth Cost$0.01–0.04/GB$0.05–0.12/GB3–5x cheaper
Availability99.99% (multi-PoP)99.9% (single DC)10x fewer outages
Error Meaning at CDN Layer Cache Strategy UX Goal
404 Not Found Origin returned 404 or edge KV lookup missed. Resource does not exist. Cache 10–60s at edge; long tail 404s should not hammer origin Help user find correct content; preserve SEO with soft-404 avoidance
502 Bad Gateway Origin TCP/TLS failure, invalid response, or timeout. CDN could not get valid HTTP. Do not cache; serve stale-if-error if available Reassure, auto-retry, provide status link; hide infra details
503 Service Unavailable Origin explicitly overloaded, in maintenance, or failing health checks / circuit breaker open. Do not cache; respect Retry-After header if present Set expectation for retry, offer alternative actions, show maintenance window

404: The Navigation Opportunity

A branded 404 should feel like a detour, not a dead end. Include global navigation, a prominent search bar, 3–4 most likely destinations based on URL pattern, and a link to your sitemap. Avoid the temptation to redirect all 404s to the homepage — Google treats that as a soft-404 and you lose crawl budget insight.

Return a true 404 status code. Never return 200 with “Page not found” text. Ensure your CDN is configured to cache the 404 body but keep the status code intact, so CDN performance metrics accurately report error ratios.

502 & 503: The Resilience Pages

These are availability events. The user did nothing wrong. Your tone should be apologetic, concise, and action-oriented: “We’re experiencing high demand. Your request was not processed — please retry in 30 seconds.” Include a Retry-After header (for bots) and a visible countdown or manual retry button (for humans). Link to a status page hosted outside your primary origin — e.g., on a separate domain or CDN-hosted static site.

For 503 during planned maintenance, return 503 with Retry-After: 3600 and a maintenance window. This tells search engines to come back later instead of de-indexing the URL.

CDN Error Handling Flow Diagram showing client request flow through CDN edge with error interception and branded page response Client Browser / Bot GET /product/123 REQUEST CDN Edge (PoP) Cache Lookup Error Interception 404 / 502 / 503 → Branded Page ORIGIN FETCH Origin App / Storage ● Timeout / 5xx ERROR Retry • Search • Home Served from Edge Cache (HIT)
Fig 1. Edge-intercepted error flow: The CDN serves a branded page from edge storage when origin returns 5xx or times out, avoiding origin dependency.

Design System for Error Pages

Your error pages are part of your design system, not an afterthought. They should reuse header, footer, and typography — but in a degraded, self-contained form.

Layout & Content Checklist

Performance Budget

An error page is rendered under duress. Users are frustrated and often on mobile. Enforce strict budgets:

Test with curl -H "Host: example.com" https://cdn-edge/__error/503 and verify content-length and cache-control. Your CDN load balancing algorithms may route 503s to a failover origin — ensure that failover also serves the same branded template to avoid inconsistent UX across PoPs.

Implementing at the CDN Layer

Implementation depends on your provider, but the pattern is identical: intercept status code, serve from edge storage, set correct headers.

1. Cloudflare Workers (Edge Function)

// workers/custom-error.js — serve branded pages from KV
export default {
  async fetch(request, env, ctx) {
    let response = await fetch(request);
    if ([404, 502, 503].includes(response.status)) {
      let key = `error/${response.status}.html`;
      let branded = await env.ERROR_PAGES.get(key, "arrayBuffer");
      if (branded) {
        return new Response(branded, {
          status: response.status,
          headers: {
            "Content-Type": "text/html; charset=utf-8",
            "Cache-Control": response.status === 404
              ? "public, max-age=30" : "no-store",
            "Retry-After": response.status === 503 ? "60" : ""
          }
        });
      }
    }
    return response;
  }
}

2. Fastly VCL

# vcl_error — generate synthetic branded response
sub vcl_error {
  if (obj.status == 502 || obj.status == 503) {
    synthetic {<!doctype html><html>... branded 503 ...</html>};
    return (deliver);
  }
}
sub vcl_deliver {
  if (resp.status == 404) {
    set resp.http.Cache-Control = "public, max-age=30";
  }
  if (resp.status >= 500) {
    set resp.http.Cache-Control = "no-store, no-cache";
    set resp.http.Retry-After = "60";
  }
}

3. AWS CloudFront Custom Error Responses + S3

Upload 404.html, 502.html, 503.html to an S3 bucket configured as a failover origin. In CloudFront > Error Pages, create custom responses:

# CloudFront custom error — via AWS CLI
aws cloudfront update-distribution --id EDFDVBD6EXAMPLE \
  --distribution-config '{
    "CustomErrorResponses": {
      "Quantity": 3,
      "Items": [
        {"ErrorCode": 404, "ResponsePagePath": "/errors/404.html",
         "ResponseCode": "404", "ErrorCachingMinTTL": 30},
        {"ErrorCode": 502, "ResponsePagePath": "/errors/502.html",
         "ResponseCode": "502", "ErrorCachingMinTTL": 5},
        {"ErrorCode": 503, "ResponsePagePath": "/errors/503.html",
         "ResponseCode": "503", "ErrorCachingMinTTL": 5}
      ]
    }
  }'

Set ErrorCachingMinTTL low for 5xx. CloudFront will serve the S3 object directly without hitting the primary origin. For deeper fundamentals, review CDN fundamentals guide and CDN DNS resolution explained to understand how failover origins interact with health checks.

Caching, Headers, and SEO Safeguards

Incorrect headers turn a helpful error page into an SEO disaster.

Enable stale-if-error and stale-while-revalidate at the edge. If origin returns 502 but you have a stale 200 in cache from 2 minutes ago, serving stale content is almost always better than showing an error. Configure this at the CDN, not just in origin headers.

Testing and Operational Checklist

Deploy error pages like any other critical service — with versioning and automated tests.

  1. Synthetic tests: Curl each error path from multiple PoPs. Assert status code, body contains brand string, and content-length < 50000.
  2. Chaos test: Block origin security group or stop origin service. Verify 502/503 branded page appears in <200ms with no origin dependency.
  3. Visual regression: Screenshot 404/502/503 on mobile + desktop; diff against baseline.
  4. Purge test: Update KV/S3 object, purge surrogate key, verify new version propagates in <5s globally.
  5. Accessibility: Error pages must meet WCAG AA — focus order, color contrast, and screen-reader announcement of error status.

Store templates in Git, build them with your static site pipeline, and deploy to edge KV/S3 via CI. Version them as error/503.v2.html and atomically switch the Worker/VCL reference to allow instant rollback.

Pro tip: Localize error pages at the edge using Accept-Language. Pre-build /errors/404.en.html, /errors/404.es.html and select the variant in your Worker/VCL. It adds minimal storage cost and dramatically improves UX for global audiences.

Branded error pages are a small investment with outsized return: lower bounce rates, fewer support tickets, cleaner logs, and better resilience during incidents. Treat them as first-class edge applications — not static afterthoughts — and your CDN will fail gracefully instead of failing visibly.

Frequently Asked Questions

Should CDN error pages be cached at the edge?

404 pages can be cached briefly (e.g., 10–60 seconds) to protect origin, but 502/503 pages should use no-cache or very short TTL (0–5s) with stale-if-error fallback. Always set Cache-Control: no-store for 5xx and use CDN tiered shielding to avoid thundering herd on recovery.

How large should a CDN custom error page be?

Keep it under 50KB total (HTML+CSS+inline SVG) and under 10KB for critical 502/503 failover pages. Avoid external fonts, JS, or images that depend on origin. Inline critical CSS and use system fonts or already-cached Google Fonts with font-display: swap.

Can I show different error pages per domain or path on the same CDN?

Yes. Most CDNs support custom error handling via Edge Workers, VCL, or Rules. You can map host/path to specific branded templates, languages, or retry logic. Use the Host and URL path as keys in your edge function router.

What's the difference between origin-generated vs edge-generated error pages?

Origin-generated pages are returned by your server and proxied by the CDN, preserving dynamic content but failing if origin is down. Edge-generated pages are stored and served directly from CDN edge memory/storage, guaranteeing availability during origin outages for 502/503 scenarios.

References & Standards: W3C Web Performance · OWASP CDN Security