Laravel maintenance mode stuck is a stressful production issue: visitors see a maintenance page even though the work should be finished, while the application may otherwise be healthy. It often happens after a deployment, a failed release script, a server restart, or a command run from the wrong application directory.

The fastest-looking response is to remove files or clear every cache. That can work by accident, but it can also hide a failed deployment or leave web and worker processes using different releases. A safer approach is to confirm what is serving the maintenance response, exit maintenance mode through Laravel where possible, then verify the live application end to end.
If the site is revenue-critical, unavailable to customers, or behaves inconsistently across servers, a focused Laravel Bug Fixing review can help trace the release and restore the application without guesswork.
How to tell whether Laravel maintenance mode is really stuck
First, separate a true Laravel maintenance response from a generic outage. A maintenance page normally has a deliberate message, often returns HTTP 503, and may look different from your normal error page. Test from an incognito browser or a command-line HTTP client so an old browser cache does not mislead you.
Check more than the home page. Try a public route, a route that normally requires login, and a health endpoint if the application has one. If every request has the same maintenance response, Laravel’s maintenance state is likely active. If only one server, hostname, or path is affected, investigate the load balancer, release path, virtual-host configuration, or cache layer before changing application files.
Also note when the issue began and what changed immediately beforehand. Useful clues include:
- a deployment that stopped midway through;
- a release script that ran artisan down but did not reach its cleanup step;
- a rollback to an earlier release;
- a symlink switch in a zero-downtime deployment layout;
- a PHP, permissions, or disk-space issue during the release; or
- multiple web nodes that do not share the same application state.
Restore the application with Laravel’s normal command first
When you have shell access, are in the directory for the release currently served by the web server, and know the deployment is otherwise ready, use Laravel’s normal command:
php artisan up
This is preferable to manually deleting a maintenance file because it lets the installed Laravel version manage its own maintenance state. Recheck the site immediately afterward with a fresh request. If the page now loads, do not assume the incident is complete: test the primary user flow, such as login, an API request, or checkout, and review the deployment output for the reason maintenance mode was not cleared automatically.
If php artisan up fails, capture its exact output. Do not switch on public debug mode to obtain more detail. Instead, review the application log and the server’s PHP or web-server error log. A command failure may indicate that the release lacks dependencies, uses an incompatible PHP version, cannot read its environment configuration, or cannot write to required directories.
Check that you are operating on the live release
A common reason Laravel maintenance mode appears stuck is that the command was successful—but it was run in the wrong directory. This is especially easy to do on hosts that keep a current symlink plus separate timestamped release folders.
Confirm the document root used by Nginx or Apache and identify the release it points to. Then compare that path with the directory where you ran Artisan. If a deploy switched the current symlink after maintenance mode was enabled, the active state may be associated with a different release than the one you are inspecting.
In a multi-server setup, perform the same check on each web node. One node may have been restored while another still serves the maintenance page. A load balancer can make this appear random: one refresh works, the next does not. Avoid repeatedly changing state until you understand whether the application runs from shared storage, individual releases, containers, or immutable build artifacts.
Understand where the maintenance state is stored
The exact implementation differs by Laravel version. Recent Laravel versions commonly use a maintenance-state file under bootstrap/cache, while older versions may use a file under storage/framework. The important point is not to memorize one path and delete it reflexively. Confirm the installed framework version and inspect the active release before making a filesystem change.
Manual removal may be a last-resort recovery option when Artisan cannot run, but it should be deliberate. Take a backup or record the file contents and permissions first. A maintenance file can contain configuration such as a retry value, redirect behavior, or a secret bypass token. Removing the wrong file in the wrong release will not fix the live site; changing permissions indiscriminately can create a new security or deployment issue.
If the state file reappears after you remove it or run php artisan up, something is putting the application back into maintenance mode. Check deployment hooks, CI/CD jobs, release scripts, container startup commands, and orchestration tasks. The correct fix is usually to repair the failing step or ensure the cleanup command runs on failure—not to keep manually bringing the site up.
Check maintenance bypass behavior without exposing the site
Laravel can be placed into maintenance mode with a secret bypass mechanism. This can allow an administrator to access the application while ordinary visitors continue to receive the maintenance response. It is useful for validation, but it is not evidence that the public site has recovered.
Do not publish a bypass URL, token, or maintenance secret in tickets, chat messages, screenshots, or logs that other people can access. Treat it like sensitive access information. Once work is complete, verify the public response from a clean browser session or an external monitoring location, not only from a bypassed session.
Rule out deployment and runtime failures before reopening traffic
Maintenance mode may have been intentional because the new release cannot boot. Before declaring recovery, check the parts of the deployment most likely to cause a second outage:
- Dependencies: Confirm Composer dependencies were installed for the release and that the deployed artifact contains the expected vendor directory.
- Environment: Check that the live release can read the intended environment file or injected variables. Never paste secrets into support requests or public logs.
- Configuration cache: A cached configuration built with the wrong environment values can make a healthy codebase fail. Rebuild caches only as part of a known deployment sequence.
- Permissions: The web user and workers need appropriate access to Laravel’s writable directories. Do not use broad permissions as a blanket fix.
- Database changes: Confirm migrations completed as intended and that the new code is compatible with the current schema.
- Workers: Queue workers and long-running processes may still run old code after a release. Restart them using your established process once the application is stable.
For a maintenance incident that followed a broader environment mismatch, compare the deployed runtime carefully rather than relying on version labels alone. PHP version, extensions, CLI versus web configuration, and filesystem case sensitivity can all differ between environments.
A safe verification checklist after Laravel comes back up
Recovery is complete only when the application behaves normally for real users. Use a short, evidence-based checklist:
- Request the public site without a maintenance bypass and confirm the expected HTTP response.
- Test the most important business path, not just the homepage.
- Check Laravel logs for fresh exceptions generated after reopening traffic.
- Confirm database connectivity and any essential third-party integration.
- Check queue backlog and worker health if the application relies on asynchronous jobs.
- Verify all web nodes and relevant domains serve the same release and response.
- Monitor briefly for recurring 503 responses, error spikes, or failed deployment hooks.
If the application comes up but now produces an exception, stop treating it as a maintenance-mode issue. Preserve the error message, request time, affected URL, recent release details, and relevant log entries. That evidence is more useful than repeatedly clearing caches or rerunning commands.
How to prevent another stuck maintenance window
A reliable deployment process should make entering and leaving maintenance mode explicit, observable, and recoverable. Use a release script that fails clearly, logs each step, and has a tested rollback plan. Add post-deploy health checks that request a real endpoint from outside the server. If a check fails, alert someone rather than silently leaving the application in maintenance mode.
For multi-node deployments, define whether maintenance state is shared and ensure every node follows the same release order. Keep the deployment user, web user, and worker process permissions predictable. Most importantly, test the deployment procedure on staging with the same release structure used in production.
Frequently asked questions
Why is Laravel still in maintenance mode after running artisan up?
You may have run the command outside the active release, another deployment process may be re-enabling maintenance mode, or different web nodes may be serving different application copies. Confirm the live document root, deployment logs, and node consistency before manually changing files.
Can I delete Laravel’s maintenance file manually?
It can be a last resort when Artisan cannot run, but verify the framework version and active release first. Record the existing file and investigate why the normal command failed or why the file persisted.
Do you work with Lumen or Laravel-based CMSs?
Yes. Lumen and Laravel-based products can have different bootstrapping, deployment, and package behavior, so the exact runtime and release process should be reviewed before applying a fix.
Symfony-only apps?
For an application built only on Symfony rather than Laravel, use a Symfony-specific troubleshooting approach. Laravel and Symfony share components, but their console commands, cache behavior, and deployment conventions are not interchangeable.
Need a Laravel bug fixed?
Provide the affected URL, when the maintenance page began, the latest deployment or server changes, the Laravel version, the exact Artisan output if available, and relevant redacted log entries. This makes it faster to identify whether the cause is release state, infrastructure, or an application failure.