WordPress Stuck in Maintenance Mode: Remove It Safely and Prevent Repeats

Was this helpful?

WordPress “Briefly unavailable for scheduled maintenance” is the software equivalent of a doorman stepping outside for a smoke and locking the building behind him.

Sometimes it clears in seconds. Other times it sits there for hours because an update died mid-flight, PHP timed out, disk filled up, or a permission model got “hardened” into non-functionality. The good news: the fix is usually simple. The bad news: you can make it worse if you treat it like a simple fix.

What maintenance mode actually is (and what it isn’t)

WordPress maintenance mode is not a “mode” in any sophisticated sense. It’s a file. Specifically, a file named .maintenance in your WordPress root directory. During core/plugin/theme updates, WordPress drops this file as a flag and checks it on every request. If it exists and is fresh enough, WordPress serves the maintenance message and stops.

That simplicity is both a feature and a trap. If an update completes normally, WordPress deletes the file. If the update is interrupted—timeout, fatal error, killed PHP worker, permissions issue, running out of disk, you name it—the file can be left behind. And your site stays “briefly unavailable” for as long as your business can tolerate embarrassment.

Maintenance mode also gets confused with:

  • A CDN or reverse proxy caching the maintenance page long after the file is gone.
  • A plugin “maintenance mode” feature that’s unrelated to the core .maintenance mechanism.
  • A broken update where the site is down for real (fatal errors), and the maintenance page is just the first symptom you noticed.

Operationally, treat maintenance mode as a lock file. Your job is to answer two questions before you remove it: (1) is an update still running, and (2) did it fail in a way that left the system inconsistent?

Fast diagnosis playbook (first/second/third)

If you have five minutes and someone is watching your screen, do this in order. The goal is to find the bottleneck fast: stuck update, broken filesystem state, or an edge cache lying to you.

First: confirm what users are actually seeing

  1. Fetch headers and content from origin (bypass CDN if you can). If you see the maintenance HTML from origin, it’s real. If only the CDN shows it, it’s cached.
  2. Check for .maintenance and its timestamp. If it’s ancient, it’s almost certainly stale.

Second: decide whether an update is still running

  1. Look for active PHP processes chewing CPU/time, and check web server logs for long-running requests around update.php or admin-ajax.php.
  2. Check WordPress update state with WP-CLI if available.

Third: validate the site won’t faceplant after you remove the file

  1. Check disk free space (updates write lots of small files and unzip archives).
  2. Check file ownership/permissions for wp-content and core directories.
  3. Look for incomplete update artifacts like wp-content/upgrade and partially extracted plugin directories.

That’s it. Don’t start randomly deleting plugin folders like you’re playing whack-a-mole with a filesystem.

Remove maintenance mode safely: the disciplined route

Yes, the common advice is “delete .maintenance.” Sometimes that’s sufficient. But in production, “sufficient” is how you get an outage that lasts longer than the maintenance banner.

Here’s the disciplined flow I use on real systems:

  1. Identify the WordPress root (don’t guess; on shared hosting it’s easy to be wrong).
  2. Confirm the file exists and read it. It contains a timestamp and sometimes tells you which update triggered it.
  3. Check whether updates are still in progress (process list, logs, WP-CLI state).
  4. Snapshot or backup before making changes if you’re on a system where rollbacks exist (VM snapshot, ZFS snapshot, hosting backup). If you have no rollback, be extra careful.
  5. Clear the lock by removing .maintenance only after you’re confident nothing is actively updating.
  6. Validate the site (front page, wp-admin, a logged-out page, a logged-in action).
  7. Finish or redo the update cleanly to get back to a consistent state.

One quote worth keeping in your head when you’re tempted to “just delete the file and walk away”:

“Hope is not a strategy.” — attributed to many ops leaders; commonly used in reliability engineering

Now let’s do the hands-on work.

Hands-on tasks: commands, outputs, decisions (12+)

Assumptions for the examples:

  • Linux host with Nginx or Apache
  • WordPress located at /var/www/html
  • WP-CLI may or may not be installed

If your paths differ, adjust them. Don’t “make it work” by copying commands blindly.

Task 1: Verify you’re hitting the origin (not a cache)

cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/ | sed -n '1,20p'
HTTP/2 503
date: Sat, 27 Dec 2025 10:18:02 GMT
content-type: text/html; charset=UTF-8
cache-control: no-cache, must-revalidate, max-age=0
server: nginx

What it means: A 503 suggests the maintenance handler (or something upstream) is serving an error. The cache-control hints it might be dynamic, but don’t assume.

Decision: If you see headers from a CDN (e.g., via or CDN-specific headers), test the origin directly (host header to origin IP, or internal LB address). If origin is fine but CDN is not, you’re dealing with caching, not WordPress.

Task 2: Confirm the maintenance page content

cr0x@server:~$ curl -sS https://example.com/ | sed -n '1,5p'
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Briefly unavailable for scheduled maintenance. Check back in a minute.</title>

What it means: That’s the canonical WordPress maintenance message.

Decision: Proceed to filesystem checks. If the content differs, you may be looking at a plugin maintenance page, a WAF block, or a custom error page.

Task 3: Find the WordPress root (don’t guess)

cr0x@server:~$ sudo find /var/www -maxdepth 4 -name wp-config.php -print
/var/www/html/wp-config.php

What it means: The directory containing wp-config.php is usually your WordPress root.

Decision: Use that directory for all further operations. If multiple results exist, map them to vhosts before changing anything.

Task 4: Check whether .maintenance exists and how old it is

cr0x@server:~$ cd /var/www/html && sudo ls -la .maintenance
-rw-r--r-- 1 www-data www-data 114 Dec 27 09:01 .maintenance

What it means: The file exists, owned by the web user. Timestamp suggests it’s been there for more than “briefly.”

Decision: If it’s older than a few minutes and no update is running, it’s likely stale and safe to remove after validation.

Task 5: Read the .maintenance file for context

cr0x@server:~$ sudo cat /var/www/html/.maintenance
<?php $upgrading = 1766826061; ?>

What it means: It records a Unix timestamp in $upgrading. WordPress uses this to decide whether maintenance mode should apply.

Decision: Convert it to human time. If it’s ancient, you’re not interrupting an active update by removing it.

Task 6: Convert the upgrading timestamp

cr0x@server:~$ date -d @1766826061
Sat Dec 27 09:01:01 UTC 2025

What it means: Maintenance started at 09:01 UTC.

Decision: If you’re now far past that, assume an update failed or got killed.

Task 7: Look for active update processes (PHP-FPM / PHP)

cr0x@server:~$ ps aux | egrep 'php-fpm|php.*wp-admin|php.*update' | head
www-data  21314  0.0  0.6 373400 53324 ?        S    10:12   0:00 php-fpm: pool www
www-data  21315  0.0  0.6 373400 53288 ?        S    10:12   0:00 php-fpm: pool www

What it means: You see PHP-FPM workers, but nothing that screams “running an update.” That’s normal traffic.

Decision: If you see a long-running PHP process tied to an update endpoint, wait or investigate logs before deleting the lock.

Task 8: Check web server error logs for update failures

cr0x@server:~$ sudo tail -n 30 /var/log/nginx/error.log
2025/12/27 09:01:32 [error] 21001#21001: *188 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Uncaught Error: Call to undefined function ..." while reading response header from upstream, client: 203.0.113.10, server: example.com, request: "GET /wp-admin/update.php?action=update-plugin&plugin=foo/bar.php HTTP/2.0"

What it means: Update request hit a fatal error mid-run. That’s a classic way to leave .maintenance behind.

Decision: Expect a partially updated plugin/theme/core. Plan to repair by reinstalling the affected component cleanly after restoring access.

Task 9: Check disk space (updates fail silently when storage is tight)

cr0x@server:~$ df -h /var/www/html
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        40G   39G  420M  99% /

What it means: 99% full. That’s not “a little tight,” that’s “your next write fails.” Updates unzip archives and create temp files; they will lose this fight.

Decision: Free space before retrying updates. Removing .maintenance may restore the site briefly, but you’ll re-break it the next time WordPress tries to write.

Task 10: Inspect the upgrade working directory

cr0x@server:~$ sudo ls -la /var/www/html/wp-content/upgrade
total 12
drwxr-xr-x  3 www-data www-data 4096 Dec 27 09:01 .
drwxr-xr-x 11 www-data www-data 4096 Dec 27 09:01 ..
drwx------  4 www-data www-data 4096 Dec 27 09:01 plugin-temp-ABcD12

What it means: WordPress uses wp-content/upgrade for temporary extraction. Leftover directories can indicate an interrupted update.

Decision: Don’t delete blindly. First restore site availability, then clean up after confirming what failed.

Task 11: Validate file ownership and permissions (common break after “security hardening”)

cr0x@server:~$ sudo stat -c '%U:%G %a %n' /var/www/html/wp-content /var/www/html/wp-content/plugins
root:root 755 /var/www/html/wp-content
root:root 755 /var/www/html/wp-content/plugins

What it means: Owned by root, not the web user. If WordPress runs as www-data, it may not be able to write updates, delete .maintenance, or create temp files.

Decision: Fix ownership to match your execution model (often www-data:www-data on Debian/Ubuntu). If you use a deploy user with group write + setgid, do that intentionally—don’t wing it.

Task 12: Remove .maintenance (only after checks)

cr0x@server:~$ sudo rm -f /var/www/html/.maintenance && sudo ls -la /var/www/html/.maintenance
ls: cannot access '/var/www/html/.maintenance': No such file or directory

What it means: The lock file is gone.

Decision: Immediately re-test the site from origin. If it’s still showing maintenance, you’re dealing with caching or a different mechanism.

Task 13: Confirm the site is back (and whether it’s actually healthy)

cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/ | sed -n '1,10p'
HTTP/2 200
date: Sat, 27 Dec 2025 10:19:44 GMT
content-type: text/html; charset=UTF-8
server: nginx

What it means: HTTP 200. Maintenance banner is not being served.

Decision: Now check wp-admin and logs. A 200 can still be a broken theme rendering a sad HTML skeleton.

Task 14: Check WordPress health with WP-CLI (if available)

cr0x@server:~$ cd /var/www/html && sudo -u www-data wp core version
6.4.3

What it means: WP-CLI can run and core is readable. Good sign.

Decision: Use WP-CLI to finish updates cleanly rather than clicking around wp-admin during an incident.

Task 15: See whether core/plugin/theme updates are pending or half-done

cr0x@server:~$ cd /var/www/html && sudo -u www-data wp plugin status | sed -n '1,12p'
Plugin name  Status   Update  Version
akismet      active   none    5.3
foo-plugin   active   available 2.1.0
bar-plugin   inactive none    1.9

What it means: At least one plugin update is available; maybe it was the one that failed.

Decision: If an update caused the incident, update in a controlled way (WP-CLI, one plugin at a time), watching logs and disk space.

Task 16: Attempt a controlled plugin update (one at a time)

cr0x@server:~$ cd /var/www/html && sudo -u www-data wp plugin update foo-plugin
Downloading update from https://downloads.wordpress.org/plugin/foo-plugin.2.1.0.zip...
Unpacking the update...
Installing the latest version...
Removing the old version of the plugin...
Plugin updated successfully.

What it means: The update path works end-to-end: download, unzip, replace, cleanup.

Decision: If this fails (permissions, disk, network), fix the underlying cause before repeating. Repeating a failed update is how you get a directory full of half-extracted plugins and regret.

Task 17: If wp-admin is broken, disable the culprit plugin fast

cr0x@server:~$ cd /var/www/html && sudo -u www-data wp plugin deactivate foo-plugin
Plugin 'foo-plugin' deactivated.

What it means: You’ve removed the plugin from the runtime without deleting files.

Decision: Use deactivation as a safety lever. Deleting plugin directories under pressure is how you create missing-file fatals if autoloaders expect files that vanish mid-request.

Task 18: If you don’t have WP-CLI, do a minimal filesystem check for half-installed plugins

cr0x@server:~$ sudo find /var/www/html/wp-content/plugins -maxdepth 2 -type f -name '*.php' | head
/var/www/html/wp-content/plugins/akismet/akismet.php
/var/www/html/wp-content/plugins/foo-plugin/foo-plugin.php
/var/www/html/wp-content/plugins/bar-plugin/bar.php

What it means: Plugin main files exist. If a plugin directory is missing its main file, it’s likely a broken install.

Decision: If a plugin is half-installed, reinstall it cleanly from a known good source (or restore from backup). Don’t “patch” random missing files.

Why it gets stuck: failure modes you can actually prove

Stuck maintenance mode is a symptom. The disease is usually one of these:

1) Interrupted update (timeouts, process kills, restarts)

WordPress updates are a sequence of writes: download zip, unpack to temp, replace files, run update routines, delete .maintenance. If PHP times out, FPM restarts, the container is redeployed, or the host reboots at the wrong time, cleanup may never happen. The site stays locked because the lock file is still there.

Proof points: error logs showing fatal/timeouts on update.php, wp-content/upgrade leftovers, and a .maintenance timestamp matching the last deploy/restart window.

2) Disk full (or inode exhaustion)

Updates are write-heavy. Not big writes—lots of small ones. A nearly full filesystem causes unpredictable failures: zip extraction fails, temporary directories can’t be created, and WordPress might not be able to remove .maintenance even if the update “mostly” succeeded.

Proof points: df -h at 95%+, ENOSPC errors in logs, and sometimes the more annoying cousin: inodes exhausted on filesystems with millions of tiny files.

3) Permissions / ownership mismatch

The web process must be able to write to certain paths during updates. Some teams lock down permissions after a security review, then forget that WordPress is not a static site generator. If wp-content is owned by root and not writable by the runtime user, WordPress can create .maintenance in one place (or via different user contexts) and fail to remove it later.

Proof points: stat shows mismatched owners, errors like “Could not create directory,” and update UI asking for FTP credentials (a relic that shows up when direct filesystem writes fail).

4) Cache layers serving stale maintenance

You removed .maintenance, you refreshed, and the banner is still there. That’s when you remember you have: CDN, reverse proxy cache, object cache, page cache plugin, browser cache, and maybe an edge worker “optimizing” HTML. Any of them can cache a 503 and keep serving it.

Proof points: origin returns 200 while edge returns 503; headers differ between origin and edge; purging cache fixes it immediately.

5) The update “succeeded” but runtime is broken

Sometimes maintenance mode is removed correctly, but the site is still down due to a fatal error introduced by the update: incompatible PHP version, missing extensions, plugin conflicts, theme issues. The maintenance banner was just a sign you were in the update path at all.

Proof points: PHP fatal errors after removing the file, wp-admin inaccessible, and logs showing missing functions/classes tied to plugin/theme code.

Short joke #1: WordPress maintenance mode is like a sticky note on the door saying “Back in 1 minute.” It’s never one minute.

Common mistakes: symptom → root cause → fix

This section exists because people keep doing the same three wrong things: guessing, rushing, and “optimizing” without rollback.

Maintenance banner persists even after deleting .maintenance

  • Symptom: .maintenance is gone, but users still see the maintenance page.
  • Root cause: Cached response (CDN, reverse proxy, page cache plugin) or you deleted the wrong site’s .maintenance (wrong docroot).
  • Fix: Verify origin response with curl to origin, confirm correct docroot via vhost config, purge edge cache if needed.

Site returns 500 after removing .maintenance

  • Symptom: Maintenance mode is gone, but now it’s a 500 or a blank page.
  • Root cause: Update left a plugin/theme half-updated; PHP version mismatch; missing extension; corrupted autoload map.
  • Fix: Check error logs; disable suspect plugins (WP-CLI or rename directory); reinstall the affected plugin/theme cleanly; confirm PHP version/extension requirements.

Maintenance mode returns immediately after you remove it

  • Symptom: You delete .maintenance, refresh, and it comes back.
  • Root cause: An update process is still running (cron, auto-updates, someone else in wp-admin) and recreating the file.
  • Fix: Stop the update activity (pause deploy pipeline, disable auto-updates temporarily, investigate cron), then remove the file once the system is stable.

Updates always fail and leave maintenance mode behind

  • Symptom: This is a pattern, not a one-off. Every update risks downtime.
  • Root cause: Filesystem not writable for the runtime user; disk pressure; network egress blocked to WordPress download endpoints; security tooling rewriting permissions.
  • Fix: Fix the execution model: consistent user/group, writable upgrade paths, adequate disk headroom, allow outbound to update sources, and stop “hardening” with chmod roulette.

wp-admin asks for FTP credentials during updates

  • Symptom: The update UI demands FTP/SSH credentials.
  • Root cause: WordPress can’t write directly to the filesystem (permissions/ownership or filesystem mounted read-only).
  • Fix: Correct ownership/permissions and mount options. If you must use immutable infrastructure, do updates via build pipeline, not wp-admin.

Only some pages show maintenance mode

  • Symptom: Homepage works, specific pages show maintenance (or vice versa).
  • Root cause: Cache inconsistency (one cache node has stale 503), or a plugin-generated maintenance page is conditional.
  • Fix: Purge caches globally; check multiple POPs; verify whether a “maintenance mode” plugin is enabled.

Three corporate-world mini-stories from the trenches

Mini-story #1: The incident caused by a wrong assumption

A mid-size company ran WordPress behind a load balancer with two app nodes. Updates were “simple”: log into wp-admin, click update, wait for the spinner to stop, and move on. One morning, marketing tried to update a plugin five minutes before a campaign launch. The site flipped into maintenance mode and stayed there.

On-call deleted .maintenance on node A. No change. They deleted it again. Still no change. So they concluded WordPress was “stuck somewhere else” and started restarting services.

The wrong assumption: that there was only one filesystem. In reality, node A and node B had separate local disks (no shared storage). The load balancer kept sending half the traffic to node B, where .maintenance still existed. Users experienced a roulette wheel: refresh and maybe you get the site; refresh and maybe you get maintenance.

Once they realized it was a multi-node consistency issue, the fix was unglamorous: remove .maintenance on both nodes, then stop doing in-place updates on pets. They moved plugin updates into an artifact build step and deployed consistently across nodes.

The lesson isn’t “use shared storage.” The lesson is: know your topology before you perform a single-host fix on a multi-host system. Distributed systems do not reward optimism.

Mini-story #2: The optimization that backfired

A different org wanted faster page loads. They added aggressive caching at the edge and configured it to cache “errors for a short time” to protect the origin during spikes. Sensible goal. Risky default.

During a WordPress core update, the site returned a 503 maintenance page for about 20 seconds. The edge cached it. Users kept getting the maintenance response for much longer than the actual update window, even after .maintenance was removed. Internally, the team saw the site working (because they bypassed the CDN on corporate network). Externally, customers saw “Briefly unavailable.” Support tickets started multiplying like rabbits with a project plan.

They purged the edge and everything recovered instantly. Then they had to explain why a 20-second update caused a much longer outage. The post-incident action was not “don’t cache.” It was: do not cache the maintenance response, do not cache 503s from WordPress paths, and configure bypass rules for /wp-admin/ and update-related endpoints.

Performance optimizations are great until they make your failure mode sticky. In production, “sticky failure” is a special kind of expensive.

Mini-story #3: The boring but correct practice that saved the day

An enterprise team ran WordPress as part of a larger platform. Nothing fancy: Nginx, PHP-FPM, MariaDB, plus a deployment pipeline that built an artifact for WordPress core and approved plugins. Editors still used wp-admin for content, but code updates were CI/CD only.

One afternoon, an auto-update was accidentally enabled on a plugin (a setting drifted during a migration). The plugin tried to update itself during peak traffic. It created .maintenance and then failed because the filesystem was read-only by design (deploy-only).

The site went into maintenance mode, but the team had two safety nets: (1) a read-only, versioned artifact meant the codebase was consistent, and (2) hourly snapshots let them roll back instantly if the filesystem got touched. They removed .maintenance, confirmed no files were modified (because they couldn’t be), disabled plugin auto-updates, and opened a change request to prevent that setting drift.

No heroics. No frantic SSH archaeology. Just clean boundaries: runtime can serve, pipeline can write. It’s not exciting, and that’s the point.

Prevention: make it boring and it stops happening

Stuck maintenance mode is usually a process problem wearing a filesystem costume. You prevent it by making updates predictable and recoverable.

Prefer controlled updates (WP-CLI or pipeline), not click-ops

Clicking “Update now” in wp-admin from a laptop on café Wi‑Fi is not a deployment strategy. It’s a trust exercise. Use WP-CLI on the server or run updates in a pipeline that can be retried, logged, and rolled back.

Keep disk headroom like you mean it

For WordPress hosts, I like to keep at least a few GB free on small volumes and more on larger ones. Updates, caches, logs, image uploads, and backups all compete for space. Disk pressure causes weird symptoms long before you hit 100%.

Make file ownership/permissions consistent

Pick one operational model and enforce it:

  • Mutable server model: WordPress can write updates. Then the runtime user must own or have write access to relevant paths. Great for small sites; risky for large ones.
  • Immutable deploy model: Runtime is read-only; updates happen in a build step. Great for reliability; requires discipline.

Mixing the two models produces the classic situation where WordPress can create .maintenance but can’t remove it. That’s not “security.” That’s a booby trap you set for yourself.

Guardrails: maintenance-mode monitors and alerts

Add a synthetic check that requests your homepage and fails if the maintenance title appears. It’s a high-signal, low-effort alert. Your customers should not be the monitoring system.

Cache rules: don’t let “briefly unavailable” become “permanently cached”

At your CDN or reverse proxy, set sensible behavior for 503 responses and for WordPress admin paths. Maintenance mode is a transient response that should not be cached broadly.

Short joke #2: Nothing says “enterprise-grade” like caching an error page at 200 locations worldwide.

Checklists / step-by-step plan

Checklist A: Get the site out of maintenance mode safely (10–15 minutes)

  1. Confirm what the user sees (origin vs cache).
  2. Locate correct WordPress root via wp-config.php.
  3. Check .maintenance existence and timestamp.
  4. Check for active updates (processes, logs).
  5. Check disk space and inodes.
  6. Check wp-content/upgrade for leftover temp dirs.
  7. Snapshot/backup if available.
  8. Remove .maintenance.
  9. Validate: homepage, a couple of deep links, wp-admin login.
  10. Review logs to confirm no continuing fatals/timeouts.

Checklist B: Repair the underlying update failure (30–90 minutes)

  1. Fix disk pressure (clear old logs, cache directories, unused backups).
  2. Fix ownership/permissions to match your model.
  3. Update via WP-CLI one component at a time.
  4. If a plugin/theme is corrupted, reinstall it cleanly.
  5. Verify PHP version and extensions match plugin requirements.
  6. Run a quick smoke test and keep an eye on error logs.

Checklist C: Prevent repeats (this is where adults earn their paychecks)

  1. Decide: mutable WordPress or immutable artifact deploy. Write it down.
  2. Add synthetic monitoring for maintenance response.
  3. Add disk and inode alerts before you hit trouble.
  4. Set CDN/proxy cache rules to avoid caching 503 maintenance pages.
  5. Schedule updates during low traffic with clear rollback paths.
  6. Keep backups/snapshots tested, not just configured.

Interesting facts and historical context

  • WordPress maintenance mode is implemented as a simple lock file (.maintenance) rather than a database flag, which keeps it fast and independent of DB state.
  • The “Briefly unavailable…” message dates back many major versions and persists because it’s reliable under partial update conditions: if PHP can read a file, it can show a message.
  • WP-CLI started as a community project and became a de facto standard because click-based updates don’t scale operationally.
  • Automatic background updates were introduced to reduce patch lag for security releases, but they also introduced a new failure mode: unattended updates on misconfigured filesystems.
  • WordPress updates work by extracting ZIP archives into temporary directories, which makes them sensitive to disk space and inode availability.
  • Many hosts historically enabled “FTP credentials” update flow because PHP often ran as an unprivileged user that couldn’t write to the site directory.
  • Some caching layers cache 503s by default as a resilience measure, which can unintentionally extend the visible maintenance window long past the actual update.
  • Plugin ecosystems create operational complexity: a single plugin update can change runtime requirements (PHP version, extensions), turning a routine update into an outage.

FAQ

1) Is it always safe to delete the .maintenance file?

Usually, yes—if no update is actively running. If an update is still in progress, deleting it can let traffic hit a half-updated codebase. Check processes/logs and the timestamp first.

2) Where is the .maintenance file located?

In the WordPress root directory (the same directory that contains wp-config.php). If you have multiple sites, each has its own root and its own .maintenance.

3) Why does maintenance mode come back after I remove it?

Because something recreates it: an auto-update retry, a cron job, or another admin session attempting updates. Stop the update trigger, then remove the file.

4) I removed .maintenance and now I get a white screen. What happened?

The update likely introduced a fatal error (plugin/theme incompatibility, missing PHP extension, broken autoload). Check PHP/Nginx/Apache error logs, then disable the suspected plugin or switch themes.

5) Can a cache make it look like WordPress is still in maintenance mode?

Absolutely. CDNs and reverse proxies can cache the maintenance response. Compare origin vs edge responses; purge caches if origin is healthy.

6) What’s the fastest way to disable plugins if wp-admin is down?

WP-CLI is fastest: wp plugin deactivate --all (then re-enable selectively). Without WP-CLI, renaming the plugin directory can work, but it’s more blunt and less auditable.

7) Does WordPress maintenance mode affect only the frontend?

It can affect both frontend and admin, depending on the request path and timing. During updates, you often can’t reliably use wp-admin until the update finishes or the lock is removed.

8) How do I prevent this during future updates?

Fix the root causes: ensure adequate disk space, consistent permissions, and a controlled update method (WP-CLI or pipeline). Also configure caches to avoid caching 503 maintenance responses.

9) Should I delete wp-content/upgrade contents?

After you restore service and confirm no update is running, you can remove old temporary directories in wp-content/upgrade. If you’re unsure, leave it until you’ve finished repairing the update; it can be evidence.

10) What if I’m on a multi-node setup?

Check every node that can serve the site. If storage isn’t shared, each node may have its own .maintenance. Also ensure updates aren’t being attempted independently on multiple nodes.

Conclusion: next steps that reduce downtime

When WordPress is stuck in maintenance mode, the mechanical fix is deleting .maintenance. The professional fix is making sure you’re not stepping over an active update, then repairing the underlying reason it got stuck.

Do these next:

  1. Verify origin vs cache and purge only when you’ve proven caching is the issue.
  2. Check disk headroom and permissions—two boring problems that cause most of the drama.
  3. Finish updates with WP-CLI (one at a time) or move updates into a pipeline.
  4. Add monitoring for the maintenance response so you learn about it before your customers do.

Make updates boring, repeatable, and observable. WordPress will still find ways to surprise you—but fewer of them will happen at 9:01 on launch day.

← Previous
Mobile Docs Navigation Drawer That Doesn’t Break: Overlay, Scroll Lock, and Focus
Next →
ZFS zpool iostat -r: Reading Latency Like a Pro

Leave a comment