Laravel Post-Deploy Checklist: Verify the Release Beyond a Green Health Check
A successful rollout needs evidence from the application, browser and background workers. Use a focused checklist before and after moving public traffic.
Define what must work before switching traffic
A Laravel release is not complete when the containers start. The new code, configuration, assets and background processes need to agree, and the public route needs to exercise the intended release. Write the acceptance conditions before deploying so that a green dashboard does not replace a missing check.
Use the checklist below as a release worksheet. It separates candidate checks from public verification and ongoing monitoring. Adapt service names, routes and authentication to your deployment. In blue-green setups, commands must target the active or candidate slot deliberately; a legacy Compose service named app may be stopped by design.
| Area | Candidate check | Public verification after the switch |
|---|---|---|
| Application | The process boots with the intended configuration | A known dynamic route returns the expected response |
| Authentication | A controlled account can complete the intended flow | Session and redirect behavior work through the real proxy |
| Assets | Manifest and files belong to the same build | Fresh and older tabs load their required CSS and JavaScript |
| Browser | Critical controls initialize without relevant errors | The main journey works at the intended viewport |
| Background work | Correct workers and scheduler run the new release | A safe canary completes through the real queue |
| Search signals | Templates expose intended robots and canonical values | Public URLs, redirects and sitemap agree |
Check health without confusing boot with readiness
Laravel's default health route reports whether the application booted successfully. It can be extended with application-specific diagnostics. Verify how your application actually configures it rather than assuming the default /up path exists or checks the database. See Laravel's deployment documentation (opens in a new tab).
From an authorized diagnostic machine, an exact-status probe can be:
status=$(curl --silent --show-error \
--connect-timeout 3 --max-time 10 \
--output /dev/null --write-out '%{http_code}' \
https://example.com/up) || exit 1
[ "$status" = 200 ] || exit 1
This fails on a transfer error and on a status other than 200. It does not check the response body or business correctness. Add an expected marker where an HTML fallback or cached page could impersonate success. Do not use an insecure TLS flag to make a failing certificate disappear from the gate.
For a public service behind Basic Auth or a CDN challenge, decide which probe path and identity are intended. Keep “not authorized to inspect” separate from “the application is down.” Do not expose a detailed dependency diagnostic publicly if it leaks infrastructure information.
Verify configuration and migrations as release inputs
Confirm that the runtime has the required configuration and that configuration caching happened at the intended point. Changing an environment file alone does not establish that a running container or cached application configuration uses the new value.
On the correct application service, these commands inspect version and migration state:
docker compose exec -T app php artisan --version
docker compose exec -T app php artisan migrate:status
Replace app with the service that actually runs the candidate or active release. Keep production credentials and complete configuration dumps out of CI logs. These inspection commands do not perform a migration or prove schema compatibility with the previous release.
Plan database changes for the overlap between versions. A destructive schema change can break the old slot even when the new one passes its checks. Migration execution and rollback policy belong in the release process, not in an improvised troubleshooting command after the public switch.
Exercise login through the real proxy
Use a dedicated account and the public HTTPS hostname to verify login, redirects and a harmless authenticated page. Check the logout flow if session behavior changed. A successful login form response does not establish that session cookies survive the next request.
Pay attention to scheme detection, trusted proxies, cookie domain and secure-cookie settings when moving between local Docker, a host proxy and Cloudflare. If authentication fails, inspect the redirect chain and cookie attributes without copying session values into a ticket.
Do not reset real customer passwords or send real password-reset emails as part of every release. Keep smoke-test identities, permissions and cleanup procedures explicit.
Check assets and the browser's actual behavior
Load a fresh page and keep a tab from the previous release for a compatibility check. Confirm that JavaScript and CSS URLs return the right status and content type, including a route that triggers a late dynamic import.
Then test a small critical journey: opening the mobile menu, searching known data or submitting a safe form. Record browser exceptions and resource failures, but require an expected visible result too. A clean console with a permanently disabled action is still a broken experience.
Take visual evidence at the viewports you support. A local fixture in this series showed that a footer-only regression changed a full-page screenshot while leaving the first screen unchanged. That is why screenshot scope belongs in the acceptance plan, not in a default chosen once and forgotten.
Verify the worker, not only dispatch
Long-lived queue workers need to load the new code. Laravel documents graceful worker restart behavior in its queue guide (opens in a new tab). Coordinate restarts with a process supervisor and allow in-progress jobs to finish according to your operational policy.
If the application uses Horizon, follow its deployment procedure (opens in a new tab) instead of assuming that a command for a different worker setup is sufficient. Inspect the queues that matter to this release, including dedicated browser or notification workers.
For scheduled work, inspect the intended schedule and confirm the scheduler process is active. A read-only starting point is:
docker compose exec -T app php artisan schedule:list
The output lists configured tasks; it does not prove execution. A safe canary or a success heartbeat after actual work completes provides a different signal. Avoid running schedule:run manually on production merely to “test” it if doing so would trigger real jobs.
Verify search signals and retain a public observation window
Sample the important page types for status, canonical, robots directives and redirect destinations. Fetch the production robots.txt and sitemap. A correct homepage does not prove that a detail-page template avoided a staging noindex tag.
After switching traffic, keep observing the public path while the old release drains. Record which release was accepted and what rollback would require. Availability, JavaScript, visual, SSL and heartbeat checks provide complementary evidence over time; they do not guarantee that a short outage between probes will be detected.
The examples here are a checklist and adaptation templates. Local experiments verified individual failure mechanisms, not a complete deployment of your application. Make the final gate reflect the features your own customers depend on, and give every failed check a clear owner and next diagnostic step.
Catch problems after your next deployment
Monitor availability, browser JavaScript errors and visual changes with DeployWatchers.