The timing is in your own hourly profile
The first question about a maintenance window is not what the maintenance page looks like, but when it gets served. The usual answer is "at night", which makes it a guess. Anyone running analytics without cookies can replace that guess with a measurement: page views per hour, averaged over four to six comparable weeks, split by weekday and weekend. The hour falls out of that curve on its own, and it is often not where intuition puts it.
Two distortions have to be accounted for. First the time zone: a curve kept in UTC in the report shifts against the local time of your visitors, and around the daylight saving time change it shifts again. Second the audience: a trade supplier selling to businesses has a sharp weekday peak in the morning, a consumer shop has two flat peaks at midday and in the evening. The same hour can be the cheapest one for one business and the most expensive one for the next.
- Page views per hour over at least four weeks, weekday and weekend evaluated separately
- Put orders, enquiries and payment drop-offs per hour next to it, not just page views
- Check the local time of your visitors, not the time zone of the reporting tool
- Account for recurring jobs: imports, end-of-day closings, interface synchronisations
- Take public holidays and campaign periods out of the average, or one outlier moves the curve
One point is regularly missed: the hour with the fewest visitors is not necessarily the hour with the least damage. If the nightly stock synchronisation with the merchandise system runs at three, a maintenance window there is more expensive than one at four, even though the visitor curve looks identical. For search engines there is another factor: the requests do not have to come from your neighbourhood. Google states in its own documentation that it generally crawls from the US. A German night hour is therefore no off-peak time for the crawler.
The visitor curve says when few people are around. The revenue curve says when little money is moving through the funnel. The second one decides the maintenance window. In shops with instalments or invoice purchase the two regularly diverge, because the background checks are tied to fixed times of day.
What the 503 status code promises
RFC 9110 describes 503 in Section 15.6.4 as a state in which the server is currently unable to handle the request because of a temporary overload or scheduled maintenance, and which will likely be resolved after some delay. That is the entire promise: not "broken", not "gone", but "not right now, later again". Exactly that meaning is missing from every maintenance page served with 200.
The 503 (Service Unavailable) status code indicates that 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.
— RFC 9110, Section 15.6.4
The counterpart is in the Google Search Central blog post of 25 January 2011 and has not been withdrawn since: instead of returning a 404 or showing an error page with status 200, it is better to return a 503, which tells search engine crawlers that the downtime is temporary. The same document names the Retry-After header as an optional way to state the length of the downtime in seconds or the estimated end, which Googlebot may use to determine when to recrawl the URL. And it warns against treating 503 as a permanent solution: lasting 503 responses can eventually be read as a sign that the server is permanently unavailable and can lead to URLs being removed from the index.
How short "temporary" is meant to be is spelled out by Google Search Central in its guidance on pausing an online business. It says that for an urgent shutdown of one to two days you return an informational error page with a 503 status code instead of all content, and in the same section that this is an extreme measure which should only be taken for a very short period of time, a few days at most. A one-hour maintenance window sits far below that line and is uncritical; a migration across a whole weekend less so.
The status code says "later again". Leaving it up for days says something other than what you mean. For longer closures Google explicitly recommends the other route: an indexable home page as a placeholder with status code 200, so users still find the business in Search.
Retry-After: two formats, one decision
RFC 9110 states in Section 10.2.3 that the value of Retry-After is either an HTTP date or a number of seconds to delay after receiving the response. For the seconds form it adds that the value is a non-negative decimal integer representing time in seconds. Sent together with a 503 response, the same section says, Retry-After indicates how long the service is expected to be unavailable to the client. Section 15.6.4 adds that the server may send such a header to suggest an appropriate amount of time to wait - a permission, not an obligation.
| Property | Seconds (delay-seconds) | HTTP date |
|---|---|---|
| Notation | Retry-After: 3600 | Retry-After: Sat, 03 Oct 2026 03:00:00 GMT |
| Reference point | receipt of the response | a fixed point in time in GMT |
| Requirement in RFC 9110 | non-negative decimal integer | the protocol date format |
| Behaviour behind a cache | stays correct, because it is relative | only with correct clocks on both sides |
| Fits | short, sliding windows | windows with a hard end date |
In practice the seconds form is the calmer route. It counts from the receipt of the response and therefore stays correct even when a response sits in a cache for a moment. The date wins where the end of the window is contractually fixed and the value should also be readable by people. In its guidance on pausing, Google Search Central simply recommends using the Retry-After HTTP header with a best effort date or duration - which of the two forms is left open.
HTTP/1.1 503 Service Unavailable
Retry-After: 3600
Cache-Control: no-store
Content-Type: text/html; charset=utf-8
Content-Length: 1184
<!doctype html>
<html lang="en"><head><meta charset="utf-8">
<title>Maintenance until 04:00</title>
<style>body{font:16px/1.5 system-ui,sans-serif;margin:3rem auto;max-width:36rem}</style>
</head><body>...</body></html>Whether the header really goes out that way is not visible in the page source, only in the response. A look at the HTTP response headers before the date costs a minute and also settles whether an upstream cache or a load balancer strips the header on the way - a case that occurs more often than the server configuration suggests.
Three delivery mistakes that are measurable before the date
The maintenance itself is planned; its delivery usually is not. Three mistakes keep coming back, and all three can be reproduced and measured on a test installation the day before.
The most common case: the maintenance page is an ordinary page and therefore answers with 200. To a search engine that is not an outage but new content. Google recommends the 503 instead and warns against blocking the site with 403, 404 or 410 status codes or with a noindex header.
The block rule is often set globally and catches robots.txt with it. Google writes that a 503 status code should not be returned for the robots.txt file because it blocks all crawling - so the damage reaches beyond the window.
A 302 to a separate maintenance URL that answers there with 200 loses the message on the way. Google states that its crawlers follow up to 10 redirect hops by default and then judge whatever they find at the end.
The second point deserves its own look, because its consequences last longest. The Google robots.txt specification describes the handling of 5xx responses for that file in stages: for the first 12 hours Google stops crawling the site but keeps trying to fetch the file. If that fails, for the next 30 days the last good version is used while the fetch attempts continue. If no cached version is available at all, Google assumes there are no crawl restrictions. For the contents of the file the same source names a usual caching period of up to 24 hours, which can be longer when refreshing is not possible, for example because of timeouts or 5xx errors.
- robots.txt is excluded from the maintenance rule and keeps answering with 200
- The block rule applies to pages and resources, not to control files
- If the file cannot be served during maintenance anyway, keep the window short
- After the window the fetch of the file is measured once, not assumed
A global redirect of all requests to the maintenance page catches robots.txt, sitemap.xml and the status page along with it. Anyone who knows the common robots.txt mistakes sets the exception before the window and verifies it afterwards instead of assuming it.
What 5xx does to crawl rate and index
Google describes the behaviour of its own crawlers on server errors in a dedicated document. The core: 5xx server errors and the 429 code prompt the crawlers to temporarily slow down with crawling. The reduction is not a flat rate but proportionate to the number of individual URLs that are returning a server error. A one-hour window affecting few URLs is therefore something different from a weekend in which every URL of the domain answers with 503.
- During the window: the crawl rate drops, already indexed URLs are preserved in the index at first
- On persistent server errors: the indexing pipeline removes URLs that persistently return a server error
- After the return to 2xx: Google states that it gradually increases the crawl rate again
One side effect is rarely considered: as long as a page answers with 503, Google states that its systems cannot refresh that page’s titles, descriptions, metadata or structured data. Anyone rolling out a price change or a new page title in the same period waits longer for it to show. Where that matters, the window does not belong in the same week as the change, and SEO monitoring runs once afterwards against the affected URLs on purpose.
The difference between a planned 503 and a silent misconfiguration matters for the evaluation. Anyone who has ever hunted for wrong status codes on error pages knows the pattern: the page looks right, the header says something else. For a maintenance window it is the same check with the sign reversed.
The maintenance page: static, light, no external resources
The maintenance page is the one page that has to work during the window - and it is precisely the one that often depends on the very infrastructure being shut down. For this case Google Search Central recommends minimising off-page resources and using inline CSS stylesheets and base-64-encoded images instead. Translated: one file, no font fetch, no connection to the content management system, no database. The 2011 blog post goes one step further and calls it a good idea to have a separate server available for planned downtime such as hardware maintenance, one that actually returns the 503.
- Status code 503 and Retry-After in the response header, not only in the text of the page
- An expected return date in plain words, so visitors do not have to guess
- A contact route that works outside the application being maintained
- Inline CSS instead of linked files, images embedded or left out
- No noindex header and no 403, 404 or 410 as a substitute for the 503
- The page lives where it stays reachable with the application switched off
Open the maintenance page once while the application is deliberately stopped. Looking at it with the system running checks a different page from the one that will be served later.
For the special case of a longer closure - company holidays, refurbishment, a seasonal break - a different recommendation applies. Google writes that for a longer shutdown you should provide an indexable home page as a placeholder with status code 200, so users can still find the business in Search. The 503 is the tool for hours and days, not for weeks.
Caching: a 503 must not get stuck
Under RFC 9110 only part of the status codes counts as heuristically cacheable; the specification lists twelve of them in Section 15.1 - 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414 and 501 - and states that all other status codes are not heuristically cacheable. So 503 is not among them, which is exactly right. It gets dangerous only when an upstream cache is handed an explicit expiration time: RFC 9111 states in Section 4.2.2 that a cache must not use heuristics to determine freshness when an explicit expiration time is present in the stored response. If a long validity ends up there by accident, the maintenance page outlives the maintenance.
A 503 with a generous validity survives the maintenance window in the delivery network and on the upstream server. That is why Cache-Control: no-store belongs in the response header of the maintenance page, and why the return is measured rather than trusted - the stale cache traps after a deploy follow exactly the same pattern.
Suppress alerts, keep measuring
A planned window without alert suppression produces exactly the alerts nobody reads - and trains the team to click notifications away. How silent windows turn into false alerts is covered in detail under maintenance windows and false alerts. The shape matters: the window needs an end, not only a start. A suppression that has to be switched back on by hand is the most common reason why the next real outage goes unnoticed.
- Set the window with a start and an end, with a buffer before the start and after the planned finish
- Suppress alerting, keep measuring - the data from that hour will be needed later
- Keep one check that looks for the expected 503 and the Retry-After header instead of a 200
- Document the window in alerting so stand-ins can see it
- Confirm once after the end that alerting is armed again
Outwards the window belongs on the status page, and it belongs there beforehand. A status page with reporting picks up the announcement and carries it through the window; how to set such a page up for customers is covered under setting up a status page for customers. The side effect is practical: whoever reads the announcement does not call.
A check that expects a 503 during the window turns the maintenance into a measurement: if the page answers with 200, the maintenance rule is not active; if it answers with 502, the maintenance page itself is gone. You want to know both during the maintenance hour, not on Monday.
The dry run before the date
Every statement in this article can be verified before the date, and in the same place where the visitors will stand later: in the response of the server. For that the maintenance rule is switched on for a test installation or a single URL and the response is read.
One measurement trap hides in the shortcut: calling curl with the follow-redirects switch returns the status code of the target, not the one of the maintenance page. A 302 to a page answering 200 shows up as a clean 200 in the output, and the redirect trap stays hidden. So measure without that switch and walk the chain step by step. For a quick look a status code test is enough, for the control files the fetch of robots.txt and sitemap.
- The status code of the home page is 503, not 200 and not 404
- Retry-After is present in the response header and carries seconds or a date
- robots.txt still answers with 200 and contains no new block rule
- sitemap.xml and the status page are excluded from the maintenance rule
- No noindex in the response header and no noindex in the head of the maintenance page
- The maintenance page loads no file that lives on the application being maintained
After the window the return is measured
The window does not end when the application runs again, but when the return is proven. Google states that it gradually increases the crawl rate again once the server starts responding with a 2xx status code - that happens on its own, but it is no substitute for your own check. The first measurement after the window is about the status code, the second about the cache, the third about alerting.
- Home page and two subpages answer with 200 again, Retry-After is gone
- No 503 left in the delivery network, sampled against several locations
- robots.txt and sitemap.xml unchanged and reachable
- Alerting armed again, maintenance window closed instead of left open
- Response times of the first hour reviewed: a cold cache looks like an outage
When something is off after the window, the cause is often not the maintenance itself but the change that was shipped with it. The procedure for that is covered under deploy errors as an outage cause; the difference to maintenance is that a rollback to the previous state stays an option here, as long as that state is kept around.
Maintenance windows in the contract and before peak season
An announced maintenance window is excluded from the availability calculation in most agreements - but only if it was announced, stayed inside the agreed frame and is documented. How to pin down measurement point, exclusions and service credits cleanly is covered under SLA disputes with the client. For agencies the practical consequence is simple: the window is announced in writing, the measurement keeps running, and both are available as evidence later.
Before peak season the calculation shifts again. What is a quiet night hour in March can be a campaign night in November. Anyone preparing for peak season traffic spikes therefore puts maintenance windows ahead of the hot phase and freezes them during it. The hourly profile from last year is a better basis for that than the one from the current month.
The statements about the 503 status code, the Retry-After header and heuristic caching come from RFC 9110 (Sections 10.2.3, 15.1 and 15.6.4) and RFC 9111 (Section 4.2.2). The statements about how Google behaves on 5xx responses, about robots.txt and about pausing an online business come from the Google Search Central documentation and from the post "How to deal with planned site downtime" of 25 January 2011. Every quotation is stored with a deep link and its wording. The hourly visitor profile comes from your own measurement and is not a figure taken from an external source.