गाइड · मॉनिटरिंग

Website Maintenance Mode Done Right With 503 and Retry-After

Put your site into maintenance mode correctly with a 503 and Retry-After. Examples for WordPress, Laravel, nginx and Apache, plus CDN caching and SEO pitfalls.

लेखक: SiteDownCheck संपादकीय टीम · अपडेट: अक्टूबर 4, 2026 · 8 मिनट पढ़ने में

A maintenance page seems like a cosmetic detail: show a friendly message, do the work, switch it off. But the HTTP status code behind that page decides whether search engines keep your rankings, whether your monitoring understands what is happening and whether a CDN helpfully keeps serving the message long after you are finished. This guide shows how to do it properly, with working configurations for the common stacks.

The core rule: send 503 with Retry-After

HTTP has a status code designed for exactly this situation. HTTP 503 Service Unavailable means the server is temporarily unable to handle the request because of maintenance or overload. The accompanying Retry-After header tells clients when to try again, either as a number of seconds or as an HTTP date:

HTTP/1.1 503 Service Unavailable
Retry-After: 3600
Cache-Control: no-store
Content-Type: text/html; charset=utf-8

or

Retry-After: Sun, 04 Oct 2026 23:00:00 GMT

The status line carries the meaning: "this is temporary, the real content still exists, come back later." The body is the human-readable page; clients that cannot read it still understand the status.

Why a 200 maintenance page is harmful

The common shortcut is to replace the site with a page that returns 200 OK. That tells every machine that the maintenance message is your content.

  • Search engines may index it. If crawlers fetch your pages during the window and receive 200 with "We'll be back soon," they can treat that text as the new content of those URLs. Rankings and snippets can be affected, and recovery takes time. A 503 tells crawlers to keep the existing indexed version and retry. Search engines are generally tolerant of 503 for a short period, and they typically slow down crawling when they see it. If the 503 persists for days, they may eventually begin treating the pages as gone, so keep planned windows short.
  • Your monitors will be fooled. A monitor checking for 200 sees a healthy site while customers see a closed sign. Conversely, a monitor correctly configured to expect a 503 can distinguish planned maintenance from an outage.
  • Redirecting everything to a maintenance URL is worse still. A 301 to /maintenance can be read as a permanent move, and a 302 loses the information about what each original URL was. Do not redirect; respond in place with 503.
  • Caches and uptime history become wrong. Your own reports show 100% uptime for a period the site was unusable.

Use the HTTP status checker to verify what you actually serve, and the HTTP header checker to confirm Retry-After is present.

Things to get right in the response

  1. Status 503 on every URL, including assets the page needs, unless the page is self-contained.
  2. Retry-After with a realistic value. Overestimate slightly; underestimating makes crawlers return too soon.
  3. Cache-Control: no-store (or at least no-cache) so neither browsers nor intermediaries keep the maintenance page.
  4. A self-contained page. Inline the CSS and use an embedded or very small image. Anything the page fetches from your own site, such as scripts, fonts or images, will also get a 503 while maintenance is active.
  5. Keep robots.txt available. Serving a 503 for robots.txt can cause some crawlers to pause crawling the entire site. That is acceptable for a short window, but if you can, serve robots.txt normally with a 200. See robots.txt and sitemap guide.
  6. Exempt yourself. Let your IP address or a secret bypass so you can test the site while visitors see the maintenance page.
  7. Do not noindex the maintenance page. It is temporary, and a noindex that gets cached somewhere can linger.

Implementation examples

nginx

Create a flag file to toggle maintenance without editing the config.

server {
    listen 80;
    server_name example.com;
    root /var/www/example;

    # Allow your own IP through during maintenance
    set $maintenance 0;
    if (-f /var/www/example/maintenance.flag) { set $maintenance 1; }
    if ($remote_addr = 203.0.113.10) { set $maintenance 0; }

    location / {
        if ($maintenance) { return 503; }
        try_files $uri $uri/ /index.php?$query_string;
    }

    error_page 503 @maintenance;

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

Run touch /var/www/example/maintenance.flag to enable and rm it to disable. The always parameter makes sure headers are added on error responses. Test with nginx -t before reloading. Replace the example IP with your own.

Apache

Add this to your virtual host or .htaccess (with mod_rewrite and mod_headers enabled):

ErrorDocument 503 /maintenance.html

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/maintenance.flag -f
RewriteCond %{REMOTE_ADDR} !^203\.0\.113\.10$
RewriteCond %{REQUEST_URI} !^/(maintenance\.html|robots\.txt)$
RewriteRule ^ - [R=503,L]

Header always set Retry-After "3600" "expr=%{REQUEST_STATUS} == 503"
Header always set Cache-Control "no-store" "expr=%{REQUEST_STATUS} == 503"

The R=503 flag with the - substitution returns the status without redirecting, and the ErrorDocument supplies the page. Create or delete maintenance.flag to toggle.

वर्डप्रेस

WordPress core already does the right thing for its own updates: while updating, it creates a .maintenance file in the site root and shows a "Briefly unavailable for scheduled maintenance" message with a 503 status. If an update is interrupted, that file can be left behind and the site stays stuck on the message. Delete .maintenance from the root over FTP or SSH to recover.

For your own planned work, you have two options:

  • A maintenance plugin, but check its response. Many default to 200. Verify with the HTTP status checker and choose a plugin or setting that returns 503.
  • A small snippet in a must-use plugin (wp-content/mu-plugins/maintenance.php):
<?php
add_action('template_redirect', function () {
    if (current_user_can('manage_options')) {
        return; // admins can still browse
    }
    status_header(503);
    header('Retry-After: 3600');
    nocache_headers();
    include WP_CONTENT_DIR . '/maintenance-page.html';
    exit;
});

Remove the file to end maintenance. Remember that full-page caching plugins may serve a cached copy before this code runs, so purge caches when you start and stop.

Laravel

Laravel has maintenance mode built in, and it returns 503:

php artisan down --retry=3600 --refresh=15 --secret="my-bypass-token"
# ... do the work ...
php artisan up

--retry sets the Retry-After header, --refresh makes the page auto-reload periodically, and visiting /my-bypass-token sets a cookie that lets you through while others see the maintenance page. You can pre-render a custom view with --render="errors::503" so that the page appears even if the framework cannot boot, which is useful during deployments that change dependencies. In multi-server setups, configure the maintenance driver to use a shared cache so all servers agree.

A static maintenance page

Whatever the stack, a simple, self-contained HTML file is the best maintenance page:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Back soon</title>
  <style>
    body{font-family:system-ui,sans-serif;max-width:32rem;margin:15vh auto;padding:0 1rem;line-height:1.5}
  </style>
</head>
<body>
  <h1>We are making improvements</h1>
  <p>The site is offline for planned maintenance and should be back by
     <strong>23:00 UTC</strong>. Orders already placed are not affected.</p>
  <p>Questions? Email support@example.com.</p>
</body>
</html>

Include an honest time estimate, what is and is not affected, and a way to reach you.

Keep a CDN from caching the maintenance page

A CDN sits between visitors and your server. If it stores the 503 page, visitors may keep seeing it after you switch maintenance off, which is a nasty failure to diagnose because your origin looks fine.

  • Send Cache-Control: no-store on the maintenance response, as above.
  • Check your CDN rules. Some configurations cache error responses for a short time by default, and explicit cache rules or page rules that force caching of everything can override your headers.
  • Consider serving maintenance from the origin rather than from the edge, so that switching it off is an origin change.
  • If you use a CDN feature that serves stale content when the origin is erroring ("stale-if-error" or "always online" style features), know what it will show. Sometimes that is exactly what you want, and sometimes it hides the notice.
  • After maintenance, purge the cache for the affected URLs, then verify from outside with the HTTP status checker. Not sure whether you are behind a CDN? The CDN detector will tell you.

Planning the window

  1. Pick a quiet time using your analytics, not a guess.
  2. Announce in advance on the site, by email to customers and on your status page with the window and expected impact. The status page guide includes a maintenance announcement template.
  3. Tell your monitoring. Schedule a maintenance window, or pause checks with a calendar reminder to resume. If you configure monitors to treat 503 as planned maintenance, make sure it is scoped to the window only. The maintenance detector can confirm what visitors receive.
  4. Have a rollback plan before you start, and a deadline for using it.
  5. Test with a bypass before lifting maintenance mode.
  6. Verify after: status 200 on key pages, no cached maintenance page, certificate valid, forms and checkout working, and the monitor returning to green. Uptime figures should reflect honestly that the window occurred; see uptime percentages explained for how maintenance interacts with reported uptime.
  7. Close the loop by marking the status page entry as complete.

Avoid long windows. If the work will take many hours, consider a design that does not need full downtime: read-only mode, a database replica, or staged rollout.

अगले कदम

सामान्य प्रश्न

Will a 503 maintenance page hurt my SEO?

Not when it is short. A 503 with Retry-After tells search engines the unavailability is temporary, so they typically keep your pages indexed and retry later. Problems come from returning 200 with a maintenance message, or from leaving a 503 in place for days.

How long should the Retry-After value be?

Use your best honest estimate of the window, and add a margin. A value in seconds such as 3600 is simple, and an HTTP date is clearer for fixed windows. Treat it as a hint: clients may not obey it exactly.

Should I use a 301 or 302 redirect to a maintenance page?

No. Redirecting loses the meaning of the original URLs and can be interpreted as a permanent or semi-permanent move. Respond with 503 on the original URL instead. See HTTP redirects 301 and 302 for how redirects are interpreted.

My site still shows the maintenance page after I turned it off. Why?

Almost always caching: a CDN, reverse proxy, caching plugin or the browser kept the response. Purge caches, confirm the origin returns 200 directly, and check that Cache-Control: no-store is on the maintenance response so it does not recur.

Does WordPress use 503 for its own updates?

Yes. During core, plugin and theme updates, WordPress shows a brief maintenance message with a 503 status. If an update fails midway, delete the .maintenance file in the site root to restore the site.

Get notified when this guide updates

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

यह पेज सामान्य जानकारी है, जिसे हमारी संपादकीय टीम ने लिखा है और दस्तावेज़ीकरण बदलने पर अपडेट किया जाता है। सर्वर और प्रदाता अलग-अलग होते हैं, इसलिए बदलाव पहले सुरक्षित तरीके से जाँचें। देखें: संपादकीय नीति और अस्वीकरण.