The short answer
Laravel's support policy sets the deadline: for every release, bug fixes are provided for 18 months and security fixes for 2 years, and major releases arrive every year, around the first quarter. An application that skips two annual upgrades is running a framework that no longer gets security fixes. For most applications the answer is an in-place upgrade, one major version at a time, with tests written first. Replacing the application in stages or rewriting it is for cases where the code cannot be upgraded safely, and the table below says when.
Where each version stands
From Laravel's release table and PHP's supported-versions page, as shown on October 10, 2026:
| Laravel | PHP versions | Released | Bug fixes until | Security fixes until |
|---|---|---|---|---|
| 13 | 8.3 to 8.5 | March 17, 2026 | Q3 2027 | March 17, 2028 |
| 12 | 8.2 to 8.5 | February 24, 2025 | August 13, 2026 (ended) | February 24, 2027 |
| 11 | 8.2 to 8.4 | March 12, 2024 | September 3, 2025 (ended) | March 12, 2026 (ended) |
| 10 | 8.1 to 8.3 | February 14, 2023 | August 6, 2024 (ended) | February 4, 2025 (ended) |
So on that date Laravel 13 is the only release still receiving bug fixes, Laravel 12 receives security fixes only, and Laravel 11 and earlier receive nothing.
| PHP | Active support until | Security support until |
|---|---|---|
| 8.5 | December 31, 2027 | December 31, 2029 |
| 8.4 | December 31, 2026 | December 31, 2028 |
| 8.3 | December 31, 2025 (ended) | December 31, 2027 |
| 8.2 | December 31, 2024 (ended) | December 31, 2026 |
| 8.1 | End of life since December 31, 2025 | |
PHP's policy is that each branch is fully supported for two years, then supported for two more years for critical security issues only. The two tables have to be read together: the framework and the language each have their own clock, and the application is unsupported as soon as either one runs out.
One reading of the first table is worth planning around. PHP 8.3 is the only PHP version inside the supported range of Laravel 10, 11, 12 and 13. An application on Laravel 10 can therefore move to PHP 8.3 first and then take three framework upgrades without touching the PHP version again, which keeps each step to one kind of change.
Upgrade in place, replace in stages, or rewrite
There are three routes. An in-place upgrade keeps the codebase and moves it through each major version. Replacing in stages is the strangler fig approach Martin Fowler describes as a gradual process of modernization: new code is built on top of, yet separate to the legacy code base, and behavior moves across piece by piece. A rewrite builds a replacement and switches over. Fowler's warning about the third is direct: replacement looks simple, but he has seen this simple-sounding plan go down in flames most of the time.
| Question | Upgrade in place | Replace in stages | Rewrite |
|---|---|---|---|
| Is it a Laravel application today? | Yes, on any version that has an upgrade guide | Plain PHP, another framework, or a Laravel version so old that packages block every step | Either, when the product itself is being redefined |
| Does the code follow framework conventions? | Mostly: routes, controllers, Eloquent, queues, standard packages | Partly: some areas are conventional, others are not | No, and the logic is not worth carrying over |
| Can you write tests around the critical paths? | Yes, through HTTP | Only for some areas; those move first | No, and nobody can say what correct behavior is |
| What blocks the upgrade? | Version constraints that newer package releases resolve | Abandoned packages, edits inside vendor, or code that depends on removed framework internals | The data model itself is wrong for the business |
| Can features keep shipping during the work? | Yes, with short pauses per version step | Yes; new features are built on the new side | Only by building them twice, or by freezing the old system |
| How do you go back? | Redeploy the previous release; keep migrations reversible | Send the route back to the old code | Only at the switch-over, and only if data has been kept in step |
| When is it the wrong choice? | When each step needs changes in code nobody understands and nothing tests | When the old and new sides cannot share sessions, authentication or the database cleanly | When the main reason is that the code is unpleasant to work in |
If the answers fall mostly in the first column, the rest of this guide is the plan. If they fall in the second, the same phases apply to each slice you move. Mixed answers are normal: upgrade the conventional core in place and replace the two or three areas that block it.
Phase 0: inventory
- Record the exact Laravel version from
composer.lock, the PHP version in production (not only on a laptop), and the database engine and version. - Check the database against what the target Laravel supports: MariaDB 10.3+, MySQL 5.7+, PostgreSQL 10.0+, SQLite 3.26.0+ and SQL Server 2017+ for Laravel 13.
- Run
composer outdated, which shows a list of installed packages that have updates available. - Run
composer audit, which lists security vulnerability advisories and detects abandoned packages. Every abandoned package needs a named replacement before you start. - For the target version, run
composer why-not laravel/frameworkwith that version. The command tells you which packages are blocking a given package from being installed; its output is your list of blockers. - Search for edits inside
vendor, forked packages and classes that extend framework internals. These are what turn a short upgrade into a long one. - List everything that runs outside a web request: queue workers, scheduled tasks, cron entries that bypass the scheduler, and long-running services.
- Note the test count and what the tests cover. Zero is an answer; write it down.
Phase 1: build the safety net
- Write feature tests for the paths that earn or move money, sign users in, and change permissions. Laravel's own advice is that most of your tests should be feature tests, because they exercise a full request.
- Run the tests in CI on every push, on the PHP version production uses.
- Add static analysis at a level the code passes today. PHPStan has 11 levels, 0 the loosest and 10 the strictest, and a baseline that records current errors so only new and changed code is reported. Larastan is the PHPStan extension for Laravel.
- Fix code style once, in its own commit, so later diffs show only real changes. Laravel Pint is built on PHP CS Fixer and has a --test option that reports style errors without changing files.
- Stand up a staging environment with the same PHP, database and queue driver as production, and a recent copy of production data with personal data masked.
- Confirm you can restore a database backup, by doing it.
- Turn on error tracking and a baseline of response times before the first change, so you can tell what the upgrade altered.
Phase 2: move PHP first
- Pick the highest PHP version your current Laravel supports, from the first table, and move to it before changing the framework.
- Read the PHP migration guide for each version you cross. Each has a section on backward incompatible changes and deprecated features.
- Run the test suite with deprecation notices visible and clear them; a deprecation in one PHP version is often a removal in a later one.
- Use Rector for mechanical changes. It describes itself as fast, deterministic PHP code upgrades and automated refactoring. Review its diff like any other pull request.
- Deploy the PHP change on its own and let it run in production before the first framework step.
Phase 3: one major version at a time
Laravel publishes one upgrade guide per major version, each written from the version before it: the Laravel 6 guide is titled Upgrading To 6.0 From 5.8 and the current one Upgrading To 13.0 From 12.x. Each guide sorts its changes by likelihood of impact. Do not skip a guide; an application three versions behind has three guides to work through.
For every step:
- Read the whole guide for that version and mark the items that touch code you use.
- Update
laravel/frameworkand the packages the guide lists, then resolve whatcomposer why-notreports. - Apply the high-impact changes, then the medium ones, then search the code for each low-impact item.
- Optionally run the community Rector rules for Laravel for that version.
- Run tests and static analysis; fix; repeat until clean.
- Deploy to staging, run the non-web jobs from your inventory by hand, then release.
- Let the release run in production before starting the next step.
What Laravel's own guides flag for the last four steps:
| Step | Minimum PHP | Laravel's estimate | Check these first |
|---|---|---|---|
| 9 to 10 | 8.1.0 | 10 minutes | Composer 2.2.0 or greater is required; set minimum-stability to stable |
| 10 to 11 | 8.2.0 | 15 minutes | When modifying a column you must now explicitly include all the modifiers you want to keep; Cashier, Passport, Sanctum and Telescope no longer load their own migrations; SQLite 3.26.0 or greater. Laravel says it does not recommend migrating to the new application structure during this upgrade |
| 11 to 12 | 8.2 (per the release table) | 5 minutes | Support for Carbon 2.x has been removed; the HasUuids trait now returns version 7 UUIDs |
| 12 to 13 | 8.3 | 10 minutes | The CSRF middleware is renamed to PreventRequestForgery and now verifies request origin; the cache config gains a serializable_classes option set to false; copying the new session config will invalidate all active user sessions if serialization changes to JSON; PHPUnit ^12.0 and Pest ^4.0 |
Read those estimates for what they are. Laravel says it strives to ensure you may update to a new major release in one day or less, and the minutes cover the framework's own breaking changes. They do not include third-party packages that have not released a compatible version, code that leans on undocumented behavior, or the time to test. The inventory in Phase 0 is what tells you how far your application is from the estimate.
Two automation options are named in the Laravel 13 guide: Shift, which it calls a community-maintained service that automates Laravel upgrades, and Laravel Boost, a first-party MCP server that provides an AI assistant with guided upgrade prompts. Either can produce the first diff. Neither replaces the tests that tell you whether the diff is right.
Phase 4: deploy and verify
- Use maintenance mode only if a migration needs it;
php artisan downshows a custom view for all requests while it is on. - Rebuild caches as part of the deploy: the optimize command caches configuration, events, routes and views.
- Restart workers. Queue workers are long-lived processes and will not notice changes in your code base; the deployment guide's reload command terminates queue workers, Reverb and Octane so they start on the new code.
- Drain or version queued jobs whose payload shape changed, so a job serialized by the old release is not run by the new one unprepared.
- Confirm
APP_DEBUGis false: Laravel warns that with it on in production you risk exposing sensitive configuration values. - Point your uptime monitor at the health route, which is served at /up and returns 200 if the application has booted without exceptions.
- Watch error rate, slow requests and failed jobs against the baseline from Phase 1. Laravel Pulse tracks slow jobs and endpoints if you have no other tool.
- Keep the previous release and a database backup ready until the new one has run through a full business cycle, including scheduled jobs.
Phase 5: modernize after you are current
Upgrading gets you onto a supported version. Modernizing is what makes the next upgrade short. Do it after, as separate changes:
- Replace each abandoned or forked package with a maintained one or with framework features that have since been added.
- Raise the static-analysis level one step at a time and shrink the baseline.
- Move logic out of controllers and closures into classes that can be tested without a request.
- Squash old migrations: schema:dump writes them into a single SQL file.
- Move loose cron entries into the scheduler so the schedule is in source control.
- Decide deliberately whether to adopt the newer application structure; it is optional, and Laravel 11 was tuned to also support the Laravel 10 application structure.
- Put the next upgrade on the calendar. With a major release each year and security fixes for two, one upgrade a year keeps an application inside support.
If the application is plain PHP or very old
Here the staged route usually fits. Put a new Laravel application in front of the same domain, send it the routes it implements and pass everything else to the old code. Fowler's article lists what an incremental replacement needs, starting with understanding the outcomes you want to achieve and deciding how to break the problem up into smaller parts. In practice the first decisions are technical: how the two sides share a login session, which side owns each database table, and how a route is switched back if the new version misbehaves. Move a read-only area first, then one with writes, and retire old code as each route leaves it. The checklist above then applies to the new side from its first day.
Older Laravel versions also need older PHP steps on the way: the Laravel 9 guide, for example, required PHP 8.0.2 or greater and estimated 30 minutes, with Flysystem 3 and Symfony Mailer as its high-impact changes. Count the hops in Phase 0 before choosing between an in-place upgrade and a staged replacement.
Frequently Asked Questions
How long is a Laravel version supported?
For all Laravel releases, bug fixes are provided for 18 months and security fixes for 2 years. Laravel 13, released March 17, 2026, has security fixes until March 17, 2028.
Is Laravel 11 still supported?
No. Laravel’s release table lists security fixes for Laravel 11 until March 12, 2026. Laravel 12 has security fixes until February 24, 2027, and its bug fixes ended on August 13, 2026.
Can we skip Laravel versions when upgrading?
The official guides are written one step at a time, for example Upgrading To 13.0 From 12.x, so every skipped version’s guide still has to be applied. Working through them in order, with a deploy after each, keeps any failure traceable to one step.
Which PHP version should a Laravel application run?
One that both Laravel and PHP still support. Laravel 13 requires a minimum PHP version of 8.3 and supports up to 8.5. PHP 8.4 has active support until December 31, 2026 and PHP 8.5 until December 31, 2027.
Should we upgrade or rewrite an old Laravel application?
Upgrade in place when the code follows framework conventions and you can put tests around the critical paths. Replace it in stages when abandoned packages or modified framework code block the steps. A full rewrite is the riskiest route; Martin Fowler writes that he has seen this simple-sounding plan go down in flames most of the time.
Versions, dates and support windows were read from the linked Laravel, PHP, Composer, PHPStan, Rector and Larastan pages on October 10, 2026. Both support tables change with every release, so check them again before you plan. This guide is drawn from that documentation; Peregrine has not published a Laravel case study, and nothing here describes a client project.
Need a second opinion on an upgrade plan? See our Laravel development service, or read how we approach API integration when the upgrade also touches third-party systems. Engagements are fixed-scope projects, monthly retainers, or a combination, agreed after a 30-minute technical discovery call.

