Maintenance mode hides your site from visitors. It does not, by default, tell search engines to come back later — and the difference is one checkbox most people never find.
"Here is the content you asked for, and it is correct." The crawler takes that at face value.
Every URL now holds an identical, thin page. Real entries are replaced by the same few sentences.
"Temporarily unable to handle this; try later." The crawler understands the absence is temporary.
Existing entries are left alone. The crawler returns after the window closes. Nothing to clean up.
Nothing errors either way. The site looks correctly hidden, because to a human it is — which is why this is worth checking rather than assuming.
Table of Contents
Why 200 is the wrong answer
An HTTP status code is a machine-readable statement about what just happened. 200 OK means here is the content you asked for, and it is correct. 503 Service Unavailable means the server is temporarily unable to handle this; try later.
A crawler that receives 503 leaves the existing entry alone and returns later. A crawler that receives 200 takes the response at face value: this URL now contains a short page saying the site is under maintenance. Do that across every URL and you have handed the index a set of pages that are identical, thin, and wrong.
The damage is quiet. Nothing errors. The site looks correctly hidden, because to a human it is.
The damage is quiet — nothing errors, and the site looks correctly hidden.
The part that makes it worse: your sitemap is still working
Taking a site into maintenance rarely disables its XML sitemap. So the sitemap keeps returning 200 and keeps listing every published URL — while each of those URLs now returns the placeholder.
That is not a passive risk. A sitemap is an invitation: it exists to tell crawlers which URLs to fetch. On the site that prompted this article, the sitemap was offering 69 URLs, and every one of them answered 200 with the same maintenance body.
A sitemap is an invitation — and this one was inviting crawlers to 69 identical placeholders.
How to check in ten seconds
Fetch your own homepage without a browser, so no cache or login gets in the way:
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/Code language: Bash (bash)
Anything other than 503 while maintenance is on is the bug. Check a deep URL too — an article, a category page — because some setups only handle the homepage:
curl -sI https://example.com/some/real/article/ | head -1Code language: Bash (bash)
You want to see HTTP/1.1 503 Service Unavailable, ideally with a Retry-After header — checking the status your server actually returns is the same habit as auditing the rest of your HTTP responses.
Fixing it
Most maintenance plugins have the setting; it is usually worded as something like “enable 503 status code to discourage search engine crawlers” and it is usually off by default. Turn it on and re-run the check above.
That default deserves a moment’s thought. A plugin whose only job is removing a site from public view ships with the mechanism that tells search engines it has been removed switched off. The safe behavior exists, costs one click, and is opt-in — while the harmful state is what you get from installing the plugin and turning it on, which is the entire user journey. When you evaluate any plugin, the defaults are part of the product.
The safe behavior costs one click and ships opt-in by default.
When the setting does not seem to work
If you tick the box and the status stays 200, the setting is probably not reaching the code. Before assuming the plugin is broken, check that you are changing the option the plugin actually reads.
This bites more often than it should, because plugins change hands and rename things. A site can end up with two option rows that look equally plausible: one left by an older version, one used by the current one. Editing the wrong one changes nothing, and nothing tells you so.
Two habits make this quick:
- Search the source for the setting name, not the option name. If the saved data contains a key the code never mentions, that key is dead — a leftover from a rename.
- Follow the accessor. If the plugin’s own getter returns something like a nested slice of its options rather than the whole array, the live option is nested. A flat option with the same field names is a different, older row.
A useful intermediate signal: if your change causes some observable difference — different cache headers, say — but not the one you wanted, you are touching live code with the wrong value, rather than editing a dead row. That distinction tells you which of the two problems you have.
When the setting cannot be saved at all
In October 2026 our own pre-launch wall turned out to be serving 200, and this time the option row was not the problem. With the Maintenance plugin by WebFactory, version 4.32, the settings screen shows “Enable 503 (Service Unavailable) status code to discourage Search Engine crawlers”; we ticked it and saved, twice, and it came back unticked each time. Reading the plugin’s code on a test site explained why: the routine that saves the settings rebuilds the options from a fixed list of fields, and the 503 field isn’t on that list. The checkbox is displayed but never stored, and every save resets it.
Because the plugin loads its settings before most snippets run, a filter on the stored option was too late. What worked was setting the value through the plugin’s own settings API early in the request, before it serves the wall:
// Maintenance (WebFactory) 4.32: its save routine drops the 503 field, so set it ourselves.
add_action( 'init', function () {
global $wf_mtnc;
if ( ! is_object( $wf_mtnc ) || ! method_exists( $wf_mtnc, 'get_options' ) ) {
return;
}
$o = $wf_mtnc->get_options();
if ( is_array( $o ) && empty( $o['blockse'] ) ) {
$o['blockse'] = '1';
$wf_mtnc->update_options( 'options', $o ); // writes once, and again after any settings Save
}
} );
Code language: PHP (php)
After that, every page answered 503 Service Unavailable with Retry-After: 3600, while robots.txt and the logged-in site were unaffected. The plugin sends the header itself once the value is set. The snippet is a stopgap, so it goes when the plugin goes at launch. The general lesson matches the one above: trust the status line, not the checkbox. Re-run the check after every save.
One more gap to know about: a maintenance page covers only what the theme renders. The REST API at /wp-json/ keeps serving your posts to anyone who asks, so if the site has to stay private rather than briefly down, lock the API down as well.
Getting back out of it
Turning maintenance off restores 200 responses, and crawlers pick that up on their next visit. If the site was in maintenance long enough for placeholder pages to be indexed, resubmit your sitemap and watch coverage for a week or so; the 503 approach avoids that cleanup entirely, which is the point of setting it before you go down rather than after — getting the response right up front is the same discipline as fixing any other failed protocol check.
Set the 503 before you go down; that beats cleaning up after.
The short version
Maintenance mode is two separate jobs: hide the site from people, and tell machines the absence is temporary. Most plugins do the first by default and leave the second to you. Check the status code before you rely on it — the whole verification is one curl command, and the failure mode is completely silent.
Frequently Asked Questions
Does a 503 hurt my search rankings?
Not for a temporary outage — that is precisely what the code is for. Search engines are designed to treat 503 as “come back later” and preserve the existing entry. Sustained 503s over weeks are a different matter, but that is no longer a maintenance window.
Should the XML sitemap also return 503?
It does not need to. Leaving the sitemap reachable lets crawlers keep an accurate picture of your URL set, and once each of those URLs returns 503 there is nothing harmful to fetch. The problem was never the sitemap; it was the 200s behind it.
What is the Retry-After header for?
It tells the crawler roughly how long to wait, in seconds or as a date. It is optional, but sending it is more informative than a bare 503 and costs nothing — most plugins that send 503 set it for you.
Will 503 lock me out of my own site?
No. Maintenance plugins exempt logged-in users, so the administrator continues to see the real site. The 503 is sent only on the anonymous path.
Why does my maintenance page still return 200 after enabling the option?
Most often the option you changed is not the one the code reads — commonly after a plugin has changed ownership or been renamed, leaving an older settings row behind. Search the plugin’s source for the setting name and check whether its own getter returns a nested structure.
How do I know a maintenance page was indexed?
Search for a distinctive phrase from the placeholder, restricted to your domain, or check the coverage report in your search console. If the placeholder text appears as the description for real article URLs, they were fetched and indexed during the outage.