Error fix · Server errors

HTTP 503 Retry-After and Maintenance Pages: Doing It Right

Serve a proper 503 Service Unavailable with a Retry-After header for maintenance windows, with nginx, Apache and CDN examples and notes on SEO and caching.

Error message503 Service Unavailable

By SiteDownCheck Editorial · Updated October 21, 2026 · 4 min read

A planned maintenance window should look different from an outage, both to people and to machines. The right response is an HTTP 503 Service Unavailable with a Retry-After header and a human-friendly page. This tells browsers, search crawlers, API clients and monitoring systems that the condition is temporary and when to try again. A 200 OK maintenance page, or a redirect to one, tells them the opposite.

This page is about serving 503s deliberately. If you are the visitor of an unplanned 503, start with fix 503 Service Unavailable. For the wider process around maintenance mode, see website maintenance mode done right.

What Retry-After means

Retry-After tells the client how long to wait before another request. It has two valid formats:

Retry-After: 3600
Retry-After: Wed, 21 Oct 2026 07:28:00 GMT

The first is a number of seconds, and the second is an HTTP date. The header is defined for 503 responses (and for 429 and some 3xx statuses). Clients are not obliged to obey it, and it is a hint rather than a guarantee, so choose a realistic value. If the work might overrun, a slightly longer value is kinder than a short one that makes everyone retry at once. Check the current HTTP 503 reference for the semantics.

Why not a 200 or a redirect?

  • Search engines may index a 200 maintenance page as your real content, and replace good snippets with "Back soon". A 503 signals "do not change what you know about this URL".
  • Redirecting every URL to /maintenance loses the original request and may be cached, especially with 301.
  • Uptime tools treat 200 as healthy, so your outage looks fine, and a hidden 503 behaves like a real failure unless you set a maintenance window.
  • API clients need a machine-readable signal to back off and retry.

Search engines generally treat a short-lived 503 as temporary. A 503 that lasts for days may eventually lead to pages being dropped from results, so check the search engine's current guidance and keep the window short. Our website downtime SEO impact guide goes deeper.

nginx

Use a flag file so you can toggle maintenance without editing config:

server {
    listen 443 ssl;
    server_name example.com;
    root /var/www/app/public;

    if (-f /var/www/maintenance.on) {
        return 503;
    }

    error_page 503 @maintenance;
    location @maintenance {
        root /var/www/maintenance;
        rewrite ^ /index.html break;
        add_header Retry-After 1800 always;
        add_header Cache-Control "no-store" always;
    }
}

Enable with touch /var/www/maintenance.on and disable by removing it. Because error_page with a named location keeps the 503 status for the page it serves, the status stays 503 while the visitor sees your HTML. Reload with sudo nginx -t && sudo systemctl reload nginx after the first setup. Allow your own IP through (allow rules or a geo/map check) if you need to test the live site during the window.

Apache

ErrorDocument 503 /maintenance.html
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/maintenance.on -f
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteRule ^ - [R=503,L]
Header always set Retry-After "1800" "expr=%{REQUEST_STATUS} == 503"

The Header line needs mod_headers. Verify the syntax for your Apache version with apachectl configtest.

Application frameworks

Most frameworks have a built-in mode. Laravel's php artisan down --retry=60 sends a 503 with a Retry-After value. WordPress uses a .maintenance file during updates, which can leave the site stuck; see WordPress stuck in maintenance mode. Check your framework's current docs to confirm the exact status and headers it sets.

CDN and load balancer

Cached error pages are the trap. If a CDN caches the 503 and you finish maintenance, visitors may still see "Back soon". Send Cache-Control: no-store on maintenance responses and purge afterward if your CDN cached it (see Cloudflare cache rules and purge). Some CDNs and load balancers can serve a static maintenance response from the edge when the origin is unreachable; check your provider's docs for custom error pages and their status codes.

Test it

curl -sI https://example.com/ | grep -iE "^(HTTP|retry-after|cache-control)"

Expect HTTP/2 503, a retry-after value and cache-control: no-store. The HTTP Header Checker and HTTP Status Checker show this from outside your network, and the Maintenance Detector tells you whether a site appears to be in maintenance mode.

Monitoring during the window

Use a scheduled maintenance window in the Uptime Monitor so planned 503s do not page you or count against uptime, and tell customers on your status page. Template wording is in status page communication templates. Afterward, confirm the site returns 200 on all key URLs, not just the home page.

Next steps

FAQ

Is Retry-After required on a 503?

No, it is optional, but it helps clients and crawlers schedule their next attempt. Without it, they pick their own retry delay.

Should a maintenance page return 200?

No. Returning 200 makes it look like normal content to crawlers and monitors. Use 503 for temporary unavailability.

How long can I leave a site returning 503?

Keep it as short as possible. A long-lasting 503 may cause search engines to reduce crawling or drop URLs, so check their current guidance.

Do browsers wait for Retry-After automatically?

Generally not. Browsers display the page and the user must reload. Crawlers and API clients are the main consumers of the header.

Get notified when this fix updates

Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.

This page is general information written by our editorial team and updated when documentation changes. Servers and providers differ, so test changes safely first. See our editorial policy and disclaimer.