HostleloBlog
SavedSearch
Visit Hostlelo

Short Planned Maintenance: HTTP 503 and Retry-After

Use HTTP 503 and Retry-After for a short maintenance window, keep robots.txt available, and verify every affected HTTP and HTTPS route.

The short answer

For short planned downtime, return HTTP 503 with Retry-After on affected URLs while keeping robots.txt available. Verify HTTP and HTTPS hosts, deep routes and the admin exception. Restore normal responses promptly; correct status codes reduce search risk but do not guarantee unchanged rankings.

Purple server boxes beside a coral wrench, a clock and a return arrow, illustrating short planned website maintenance.
Reading options

On this page

If your site has to go offline for planned work, answer every request with a 503 status code and a Retry-After header, and keep the outage short. That tells browsers and Googlebot "closed for now, come back later" instead of "this page is gone" or "this error page is the real content".

Here is the fact that makes this urgent. Google's own crawling troubleshooting guide says returning 503 or 429 for more than 2 days will cause Google to drop those URLs from the index.

By the end of this guide you can put an Apache or Nginx site into a proper 503 maintenance mode, prove it with one curl command, and switch it off cleanly.

What a 503 response actually says

A status code is the three-digit answer your server gives to every request: 200 means "here you go", 404 "not found", and 5xx "server problem".

RFC 9110, the current HTTP standard, defines 503 Service Unavailable in section 15.6.4. It says the server "is currently unable to handle the request due to a temporary overload or scheduled maintenance, which will likely be alleviated after some delay".

The same section says the server MAY send a Retry-After header, which section 10.2.3 explains. With a 503, Retry-After "indicates how long the service is expected to be unavailable to the client". The value is either a number of seconds or an HTTP date.

Think of a small shop. A 503 with Retry-After is the "Closed" sign on the door with a note saying "Back at 3pm". A 200 maintenance page is the door left open with an empty counter, and every inspector who walks in assumes the empty counter is what you sell.

Before you start

  • You know which web server runs your site: Apache, LiteSpeed or Nginx. Your host can tell you, and our guide on what web hosting is explains the moving parts.
  • You can edit .htaccess or the Nginx config, through cPanel File Manager, SFTP or SSH.
  • You know the public IP address you will work from, so you can let yourself in.
  • You have a static maintenance.html page. Google recommends static HTML, inline CSS and few outside resources for a 503 page, plus the expected return time and how to contact you.
  • You have curl on your computer for testing.
  • You will back up the file before editing. The steps show how.

Made-up example: the owner of example.com plans a database upgrade on Saturday 24 October 2026 from 02:00 to 03:00 UTC. That invented one-hour window means Retry-After is 3600 seconds, and the owner works from the example IP 203.0.113.25.

Why a 200 maintenance page is a ranking risk

Many maintenance plugins show a "back soon" page with a 200 OK status. Visitors see a notice. Google sees content.

Google's status code documentation says that for a 2xx response, Google considers the content for processing, and if it looks like an error or an empty page, Search Console shows a soft 404 error. Google's troubleshooting guide defines a soft 404 as a page telling the user the page does not exist while returning 200, and says such pages are excluded from Search.

A 503 avoids that. Google says content from a URL that returns 5xx is ignored, crawlers temporarily slow down, and already indexed URLs are preserved in the index, but eventually dropped.

Why this matters: "eventually dropped" is the part people miss. A 503 buys you time, not unlimited time.

How long Google tolerates a 503

At the time of writing (20 October 2026), Google's "Troubleshoot Google Search crawling errors" page says: "Googlebot will retry these URLs for about 2 days." It also says: "returning 503 or 429 for more than 2 days will cause Google to drop those URLs from the index."

The "Temporarily pause or disable a website" page says disabling a whole site "should only be taken for a very short period of time (a few days at most)". It adds: "If you need to urgently disable the site for 1-2 days, then return an informational error page with a 503 HTTP response status code instead of all content."

Heads up: that page also warns Google cannot refresh titles, descriptions, metadata or structured data while a page returns 503. Do not bundle SEO changes into the maintenance window.

When a 503 is not the right tool

  • The closure will last longer than a day or two. Google recommends keeping the site online with limited functionality, or for a longer full closure, an indexable home page with a 200 status code.
  • Only the cart or checkout is broken. Disable that feature and keep everything else serving 200.
  • A page is gone for good. Return 404 or 410.
  • A page has moved. Use a 301 redirect, as you would when you force HTTPS on Apache.
  • You want to hide a temporary closure. Google says 403, 404, 410 or noindex remove your URLs from Search, so do not use them for this.

The common mistake: sending everyone to the home page

A tempting shortcut is one rule that redirects every URL to the home page or to a maintenance page that returns 200. It feels tidy, but Google's status code page says content from a redirecting URL is ignored and the target's content is processed instead.

Every product page and post now points at one 200 page saying "we're closed", so Google processes that single page instead of your real content. A 503 keeps each URL saying "I still exist, try again shortly".

Set up a 503 maintenance mode on Apache or LiteSpeed

Step 1: Make a backup copy first

A typo in .htaccess can take the whole site down, so copy it first. In cPanel, open Files then File Manager, click Settings and tick Show Hidden Files (dotfiles).

Download a private copy of .htaccess over SFTP, or use File Manager's Copy action with a destination your host has confirmed is outside every document root, alias and symlinked public path. Do not create .htaccess.bak alongside the public file.

For SSH, run this illustrative Bash block from the document root after replacing the private-parent placeholder with an existing writable directory confirmed by your host. These backup commands have not been executed on your server:

(
  set -eu
  umask 077
  private_parent='/absolute/non-public-backups'
  test -d "$private_parent" && test -w "$private_parent"
  backup_dir="$(mktemp -d "$private_parent/maintenance.XXXXXXXX")"
  cp -- .htaccess "$backup_dir/htaccess.backup"
  chmod 600 "$backup_dir/htaccess.backup"
  ls -ld "$backup_dir" "$backup_dir/htaccess.backup"
)

Record the generated absolute backup path and keep a protected off-server copy. The new backup directory should allow only its owner, and the file should have mode 600. A dot-prefixed name is not an access control. Only the static maintenance.html page belongs in the document root.

Step 2: Add the 503 rules

This block sends a 503 to everyone except 203.0.113.25, serves your maintenance page as the body, leaves robots.txt reachable, and only runs while a file named maintenance.enable exists. Put it at the very top of .htaccess. Each directive comes from the Apache docs, but this exact combination is not shown in them, so test with curl before relying on it (see the check section below).

# Maintenance mode: active only while maintenance.enable exists
ErrorDocument 503 /maintenance.html

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

# Tell clients when to come back, only on 503 responses
Header always set Retry-After "3600" "expr=%{REQUEST_STATUS} == 503"

Why each piece is there, from the Apache 2.4 docs:

  • ErrorDocument uses a local path. Apache warns that a full remote URL makes the client receive a redirect status instead of the original error code.
  • The -f test checks that maintenance.enable exists, so you switch maintenance on and off with one file.
  • The - substitution leaves the path untouched.
  • [R=503] works because for codes outside 300 to 399, mod_rewrite drops the substitution and handles the response through the normal error path, including ErrorDocument.
  • Header always set is needed because headers in the always table are added even on errors and persist across internal redirects such as ErrorDocument handlers.

Heads up: behind a CDN or proxy, REMOTE_ADDR may hold the proxy's address, not yours. The mod_rewrite docs point to mod_remoteip for that case.

Step 3: Switch maintenance on and off

Create an empty file named maintenance.enable in the document root. In File Manager, click + File in the toolbar; over SSH, run touch maintenance.enable.

When the work is done, delete maintenance.enable. The rules can stay in place for next time.

A note on LiteSpeed and cPanel

Some cPanel hosts run LiteSpeed instead of Apache. LiteSpeed's migration FAQ calls it a drop-in replacement that "tries to match Apache rewrite rules as much as it can", and lists differences such as its [L] flag behaving like Apache's [END]. The rules above should carry over, but confirm with the curl test rather than assuming.

Set up a 503 maintenance mode on Nginx

Step 1: Back up the server config

Find the file holding your site's server block and copy it into a protected configuration-backup directory outside all served paths. Use an explicit source and private destination confirmed by your administrator. Keep the original path and permissions in your rollback record. Do not put the backup in the website root.

Step 2: Add the maintenance rules

This schematic example uses geo to set a variable from the visitor's IP, returns 503 in the location it protects, serves maintenance.html and adds Retry-After. The geo block belongs in the http context. It is an unexecuted configuration example, not a replacement for your existing server block.

Apply and test the policy in the actual HTTPS virtual host as well as any HTTP host you keep accessible. The listen 80 line below alone cannot protect HTTPS traffic. Exact, regex, PHP and proxy locations can take precedence over location /, so your administrator must review and gate those routes too. Preserve your certificate, upstream and application configuration.

# In the http context
geo $maintenance {
    default        1;
    203.0.113.25   0;
}

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

    error_page 503 /maintenance.html;

    location = /maintenance.html {
        internal;
        add_header Retry-After 3600 always;
    }

    location = /robots.txt {
    }

    location / {
        if ($maintenance) {
            return 503;
        }
        # your normal site config continues here
    }
}

From the nginx.org docs:

  • return stops processing and sends the code. error_page makes an internal redirect to your page, and only changes the code if you add the =response syntax, so leave that out.
  • internal means visitors cannot open /maintenance.html directly.
  • add_header alone only covers codes like 200, 301 and 304. The always parameter adds it regardless of the response code.
  • In if, a variable is false when it is empty or "0", which is how your IP skips the 503.

Step 3: Test the config and reload

The -t flag checks syntax and tries to open every file the config refers to, so run it before reloading.

sudo nginx -t
sudo nginx -s reload

Only reload if the test reports no errors. To end maintenance, change default 1; to default 0;, test and reload again.

Variants

  • HTTP date instead of seconds. RFC 9110 allows dates such as Retry-After: Fri, 31 Dec 1999 23:59:59 GMT. For the made-up window that is Retry-After: Sat, 24 Oct 2026 03:00:00 GMT. Seconds never go stale if your window slips.
  • Several admin IPs on Nginx. geo accepts more lines, including CIDR ranges such as 192.0.2.0/24 and IPv6 prefixes such as 2001:db8::/32.
  • Apache server config. ErrorDocument, RewriteRule and Header are also allowed in server config and virtual host context. After editing the main config, run apachectl configtest, which reports Syntax Ok or the error.

How to check it worked

Test from a network other than your allowlisted IP, such as mobile data. This is the check Google's pause guide uses: a GET request that prints only the headers.

curl -I -X GET "https://example.com/"

You should see lines like these near the top, with other headers around them.

HTTP/1.1 503 Service Unavailable
Retry-After: 3600
Content-Type: text/html

Then check deep content, a PHP route, a static asset and any proxy route that should be unavailable. Repeat for every public HTTP/HTTPS hostname. Each affected URL should return 503 without a redirect; one successful homepage test does not prove every Nginx location is gated. Check https://example.com/robots.txt too: it should return 200, because Google says a 503 on robots.txt blocks all crawling.

Quick tip: repeat the test from your allowlisted IP. A normal 200 proves the exception works.

Troubleshooting

Problem 1: the test shows 200 with the maintenance text. Symptom: the first line reads HTTP/1.1 200 OK but the body says "down for maintenance". Cause: a plugin is drawing the page, the rule is not matching, or Nginx has error_page 503 =200. Fix: turn off the plugin's maintenance mode, remove any =200, and keep the block at the top of .htaccess.

Problem 2: the test shows a 302 redirect. Symptom: a 302 with a Location header pointing at your maintenance page. Cause: ErrorDocument or error_page uses a full URL, which both Apache and Nginx document as producing a redirect. Fix: use a local path starting with /.

Problem 3: the 503 is there but the retry header is missing. Symptom: correct status, no Retry-After. Cause: Header set without always on Apache, or add_header without always on Nginx. Fix: add always and test again.

Problem 4: every page shows 500 Internal Server Error. Symptom: the whole site breaks right after editing. Cause: a typo, a module that is not enabled, or a status code httpd does not recognise, which the mod_rewrite docs say produces a 500. Fix: restore .htaccess from the recorded private backup path, then re-add the block carefully and check your error log. Use the generated path saved in Step 1, not a guessed backup filename.

Problem 5: you are locked out too. Symptom: your own office also gets the 503. Cause: your public IP changed, or a proxy hides your real IP. Fix: check your current IP, update the rule, and ask your host about mod_remoteip if a proxy is involved.

Problem 6: pages drop out of Search Console days later. Symptom: URLs stop appearing in Google Search. Cause: the 503 ran longer than about 2 days, or robots.txt returned 503 too. Fix: end maintenance, confirm 200 responses, and ask Google to recrawl key pages through Search Console or a sitemap.

Pro tips and security notes

  • Pick your quietest hour. Check your traffic stats and keep the window short.
  • Keep the maintenance page static. If the database is what you are upgrading, a PHP page will fail too.
  • Never block all crawling for a closure. Google warns that a robots.txt disallowing everything may remove your content and URLs from Search.
  • Keep the allowlist tight. Use single IPs and remove them afterwards, since anyone listed sees your half-finished site.
  • Do not leak details. No software versions, file paths or error messages on the maintenance page.

Choosing a host? Our small business hosting checklist covers what to ask about server access.

The one message worth forwarding

Copy this message to your developer or hosting support before the next window and fill in the brackets.

Hi, we have planned maintenance on example.com on [date] from [start] to [end] UTC. During that window, please make every URL return HTTP 503 Service Unavailable with a Retry-After header set to the window length in seconds, serve a static maintenance page as the 503 body, keep robots.txt returning 200, allow my IP [your IP] through, and do not use redirects or a 200 maintenance page. Please confirm with curl -I -X GET https://example.com/ that the response shows 503 and Retry-After, and switch it off as soon as the work finishes, within 2 days at most. Thanks!

Takeaway: a short 503 with Retry-After tells search engines you are coming back, while a 200 page or a blanket redirect tells them something else entirely.

Reader questions

What does a 503 status code mean?

RFC 9110 defines 503 Service Unavailable as the server being temporarily unable to handle the request due to overload or scheduled maintenance. It tells clients the problem is temporary.

What is the Retry-After header?

It tells clients how long to wait before trying again. With a 503, RFC 9110 says it indicates how long the service is expected to be unavailable, given as seconds or an HTTP date.

How long can I serve a 503 before Google drops my pages?

Google's crawling troubleshooting guide says Googlebot retries for about 2 days, and returning 503 or 429 for more than 2 days will cause Google to drop those URLs from the index.

Why not show a maintenance page with a 200 status?

Google processes 200 responses as real content, and an error-looking page with 200 can be flagged as a soft 404 and excluded from Search. A 503 tells Google to ignore the content and come back.

Should I block robots.txt during maintenance?

No. Google says a 503 on robots.txt blocks all crawling, and a robots.txt that disallows everything may remove your content from Search, so keep robots.txt returning 200.

Why is my Retry-After header missing on the 503?

On Apache, use Header always set rather than Header set; on Nginx, add the always parameter to add_header. Without it, the header is not added to error responses.

What if my site needs to be offline for a week?

Google recommends limiting functionality instead of disabling the site, or serving an indexable home page with a 200 status for longer closures. A 503 is meant for 1 to 2 days at most.

Sources & further reading

  1. RFC 9110: HTTP Semantics (sections 10.2.3 and 15.6.4)
  2. Google: How HTTP status codes affect Google's crawlers
  3. Google: Debug network and DNS errors for Google's crawlers
  4. Google Search Central: Troubleshoot Google Search crawling errors (soft 404s)
  5. Google Search Central: Temporarily pause or disable a website
  6. Apache HTTP Server 2.4: RewriteRule flags
  7. Apache HTTP Server 2.4: mod_headers
  8. Apache HTTP Server 2.4: core (ErrorDocument)
  9. nginx: ngx_http_rewrite_module (return, if)
  10. nginx: ngx_http_headers_module (add_header)

What changed

Removed the ranking guarantee; moved configuration backups outside served paths; clarified HTTPS and Nginx location coverage and unexecuted examples; added an original maintenance cover.

Originally published . About our editorial updates.

Your next project deserves a better foundation.

Explore hosting built for your next chapter.

Explore hosting

Find your next answer.

Search published guides and articles.

Ctrl / ⌘ K to open · Esc to close