While a plugin or core update runs, visiting the site can show a short “Briefly unavailable for scheduled maintenance” message. Normally it disappears on its own. But if an update is interrupted (a closed browser tab, a dropped connection), it is natural to wonder whether the site will be stuck on that screen forever.
The mechanism behind it is a single small file in the site root: .maintenance. This article reads the WordPress 7.1.2 core source to show when the file is created, how it is judged, and when it stops mattering, then covers wp maintenance-mode and a sensible order of checks when an update seems to have stalled.
Note: everything here comes from reading core source and running
wp maintenance-mode status(display only) on this blog’s server. I did not put the live site into maintenance mode to test it.
Maintenance mode is just “does .maintenance exist?”
There is no maintenance switch in the admin screen. When an update starts, core writes .maintenance to the root directory (next to wp-config.php), and removes it when the update ends. The maintenance_mode() method of WP_Upgrader writes this single line:
<?php $upgrading = 1790000000; ?>
$upgrading is the UNIX timestamp of when the file was created. The file is a record of the start time; it carries no message text or settings.
In the source, maintenance_mode( true ) is called right before plugin updates, theme updates and background auto-updates, and maintenance_mode( false ) after they finish. If the process runs to the end, the file is always deleted.
Core checks the file on every request
Early in startup (wp-settings.php), WordPress calls wp_maintenance(). In short:
wp_is_maintenance_mode()decides whether maintenance is active.- If not, the request continues normally.
- If so,
wp-content/maintenance.phpis shown when present. - Otherwise a short default message is returned with HTTP 503 and a
Retry-After: 600header.
503 means “temporarily unable to respond,” which tells search engines to come back later. Retry-After: 600 suggests retrying after 600 seconds. For status codes in general, see “HTTP Status Code Basics.”
The key detail: the file expires after 10 minutes
wp_is_maintenance_mode() does not only check existence. Reading the source, the order is:
- No
.maintenancefile, or WordPress is installing: not in maintenance. - Load the file and read
$upgrading. - If the current time minus
$upgradingis 10 minutes (600 seconds) or more, maintenance is considered over. - While core scrapes for fatal errors (the
wp_scrape_keymechanism): not in maintenance. - If the
enable_maintenance_modefilter returnsfalse: not in maintenance.
I ran the same comparison with PHP on the server:
php -r 'define("MINUTE_IN_SECONDS",60); $u=time()-700;
echo (time()-$u)>=10*MINUTE_IN_SECONDS ? "expired" : "active", PHP_EOL;'
# → expired (a file created 700 seconds ago is treated as expired)
So even if an interrupted update leaves .maintenance behind, core stops treating the site as in maintenance about 10 minutes after creation. The default behavior is not designed to stay “under maintenance” forever.
Note: the expiry depends on the
$upgradingvalue written inside the file, not the file’s modification time. Editing that number to a later time extends the period.
If it still looks stuck, check in this order
- Is the update still running? If it has been under 10 minutes, waiting is often the right call. Deleting
.maintenancewhile an update is in progress can leave it half-finished while the site returns to normal display. Confirm it has really stopped before touching anything. - Ask WP-CLI.
wp maintenance-mode statusandis-activeonly read state.activatecreates the file anddeactivatedeletes it. On this blog,statusprintedMaintenance mode is not active. - Look at the file and the clock.
ls -la .maintenance,cat .maintenance, anddate +%s. A difference above 600 seconds means it has expired as far as core is concerned. - Suspect something other than maintenance mode. Page caches or a CDN may hold on to the 503 response longer than the real state (depending on configuration). A custom
wp-content/maintenance.phpreplaces the default message and may behave differently. And a fatal error during the update would show an error screen, not the maintenance message. - If the update truly ended and only the file remains,
wp maintenance-mode deactivateis fine. Then confirm the updated plugin or theme works. If an update stopped midway, run it again to complete it.
Practical notes
- Every update has a window where the site returns 503, so avoid peak hours.
- A long-lived 503 can affect crawling, so check early if something looks stuck.
- A hand-made
.maintenancealso expires after 10 minutes. For longer planned downtime, usewp-content/maintenance.phpor a dedicated approach. - When running updates across several sites, keep a record of which site is updating and which has finished. See “wp cli alias for managing multiple sites.”
Summary
WordPress maintenance mode is one file, .maintenance, containing $upgrading = <creation time>;. It is written when an update starts and deleted when it ends. Core checks it on every request and, even if the file exists, treats it as expired once 10 minutes have passed.
So a leftover file normally stops mattering in about ten minutes. If the screen still seems stuck, check whether the update is still running and whether a cache or custom maintenance.php is holding the display, then use wp maintenance-mode deactivate only once the update has really finished. Verify first, delete second.