Laravel upgrades
Laravel 11 to 12: the official estimate is 5 minutes. Here’s what takes longer
Laravel’s 11 to 12 guide is one of its shortest, and the composer change really is quick. What takes longer are a few behaviour changes that throw no errors: they alter dates, IDs and file paths while your application keeps running. Here’s how we’d look for them.
By itmarkerz Technologies. Updated 30 October 2026.
First decide if 12 is your destination
Laravel 11’s security fixes ended on March 12, 2026. Laravel 12’s end on February 24, 2027, so stopping there gives you a few months before the same conversation comes round again. Our Laravel 11 end-of-life guide makes the case for going straight to 13.
The changes below apply either way, because they arrive at version 12 and carry on into 13. The only reason to stop at 12 is a hard block on PHP 8.2 or a package with no Laravel 13 release. Our package matrix lists the lines that stop at 12.
Step 1: the composer change
The official guide lists three dependencies:
"laravel/framework": "^12.0",
"phpunit/phpunit": "^11.0",
"pestphp/pest": "^3.0"If Composer refuses, composer why-not laravel/framework ^12.0 shows which package is responsible. Update blocking packages on your Laravel 11 branch and release them first, where you can. That way a package’s own breaking changes don’t get mixed up with the framework’s.
Step 2: Carbon 3
The guide rates this low impact, and for many applications it is. We check it first because it’s the change most likely to produce a wrong number with no error. Laravel 11 allowed Carbon 2 or 3. Laravel 12 allows only 3, so find out where you are:
composer show nesbot/carbon | grep versionsIf you’re already on Carbon 3, this step is done. If you’re on 2, the concern is diffInDays(), diffInHours() and the rest of that family. As the Laravel 11 guide warns, they now return floats and can be negative, showing direction. A subscription that was “3 days” overdue might now be -3.25. Search for diffIn and pay most attention to invoices, overdue notices, SLA timers, report buckets and anything stored in an integer column. Then write a test for each one that matters before you upgrade, so you can compare the results afterwards.
Step 3: UUIDs
The HasUuids trait now creates version 7 UUIDs. Existing rows don’t change, and most applications are unaffected. Look harder if any of these apply:
- A validation rule, database check or regular expression expects a particular UUID version.
- Another system receives your IDs and is strict about the format.
- Your code assumes an ordering across old and new records. A table will now hold both kinds, so sorting by ID may not match the order they were created in.
To keep the previous format, use HasVersion4Uuids instead. If you imported the now-removed HasVersion7Uuids trait, switch to HasUuids, or you’ll get a fatal error rather than a subtle one.
Step 4: where your files are
If config/filesystems.php doesn’t define a local disk, its root moves from storage/app to storage/app/private. So older files seem to vanish, because the application is now looking one folder deeper. Open the config file. If local is defined there with a root, as it is in most published configs, nothing changes for you. If you’ve removed it, define it with the old root before you upgrade.
Step 5: the smaller changes, by where they bite
| Change | Who notices | How to check |
|---|---|---|
The image rule rejects SVG | Anyone uploading logos or icons | Search for image rules. To allow SVG, use image:allow_svg. Only do so if you sanitise or safely serve them |
| The container respects default property values | A class with ?Carbon $date = null now gets null, not a resolved instance | Look at constructors with nullable class-typed defaults that you resolve from the container |
Schema::getTables() includes all schemas | Multi-schema databases and tenancy code | Pass schema: where you meant one schema. getTableListing() now returns qualified names |
mergeIfMissing() treats dots as nesting | Code merging keys that literally contain a dot | Search for mergeIfMissing |
| Duplicate route names | Uncached routing now matches the first route registered, as cached routing did | Look for duplicate names in php artisan route:list |
Concurrency::run keeps array keys | Code passing associative arrays and reading results by position | Search for Concurrency::run |
DatabaseTokenRepository takes seconds | Custom password-reset token setups only | Look for code that constructs this class by hand |
A few more changes are aimed at package authors and custom database drivers, such as the Blueprint and Grammar constructors. If you maintain those, read the full list. Most applications can skip them.
Step 6: prove it
- Run your tests, but expect test tooling changes first, since PHPUnit 11 and Pest 3 have their own upgrade notes.
- Upload a file and read it back. Download one that was stored before the upgrade.
- Compare date-based output between old and new on the same data: an invoice, an overdue list, a monthly report.
- Create a record with a UUID and pass it through whatever consumes it.
- Release with the previous version ready to redeploy, and check your logs for a few days.
Do you need help with this?
Often not. A small, well-tested application can follow this page and our upgrade checklist in a short sprint, and an automated tool may cover much of the code change. Bring in someone else when your tests are thin or the date and billing logic is too important to check by eye. Our upgrade service gives you a fixed price after a free assessment. Next, the Laravel 12 to 13 guide covers the following step.
Upgrades we have delivered
Cabinet manufacturer's ordering, dealer-portal and inventory system moved from PHP 5.6 and MySQL 5.0 to Laravel 13 on PHP 8.5 and MySQL 8, with a new Next.js front end. Eight months, workflows preserved, now live.
- Sector
- Manufacturing
- Region
- Canada and US
- Stack
- Laravel 13, PHP 8.5, MySQL 8, Next.js
- Engagement
- Upgrade, about eight months, live
Loyalty-card management system we first built on PHP 5.6, re-platformed onto Laravel with all cards, balances and rules preserved. Two months, live since mid-2026, Indian client.
- Sector
- Retail & loyalty
- Region
- India
- Year
- 2026
- Stack
- Laravel
- Engagement
- Upgrade of our own earlier build, two months
Questions
How long does the Laravel 11 to 12 upgrade take?
Laravel’s guide estimates 5 minutes, and that’s fair for changing the version constraint on a clean application. The real time depends on your tests, your packages, and whether any of the behaviour changes below touch code that matters to you.
Does Laravel 12 change my existing UUIDs?
No. Stored IDs stay as they are. New records created with the HasUuids trait get version 7 UUIDs, so a table can hold both formats. That’s fine unless something validates or sorts on the old format.
Should I stop at Laravel 12 or go to 13?
Go to 13 unless you’re stuck on PHP 8.2. Laravel 12 security fixes end on February 24, 2027, while Laravel 13 has them until March 17, 2028.
Do I need to change my PHP version for Laravel 12?
Not to install it. Laravel 11 supports PHP 8.2–8.4 and Laravel 12 supports PHP 8.2–8.5. But php.net ends PHP 8.2 security support on 31 December 2026, so if you’re on 8.2 you’ll want to move soon anyway.
More on Laravel upgrades
- Laravel package compatibility matrixWhich release of each common package allows which Laravel and PHP version.
- Laravel 12 end of life: what to do firstThe security deadline, and the two things that block Laravel 13.
- PHP 8.2 end of life for Laravel teamsChoosing between PHP 8.3, 8.4 and 8.5 before the deadline.
- Laravel on PHP 8.5: what actually breaksDeprecations to search for, including the PDO constants.
- Upgrading from Laravel 10 to 11You can keep your structure. Here’s what you can’t keep.
- Upgrading Laravel 5–9Step through each version, move to a fresh install, or rebuild.
- Laravel Shift or an upgrade teamWhen an automated tool is enough, and when it isn’t.
- Filament upgrade path to Laravel 13Which order to move in from Filament 2, 3, 4 or 5.
- Which Laravel version do you need for the AI SDK?The version floors, and what to do if you’re below them.
- Laravel 14: release window and how to planWhat’s known, what isn’t, and what to do today.
- Inherited a Laravel app? The first 10 daysAccess, backups, an inventory and a safe deploy, before any new features.
- Laravel 11 end of life: what to do nowStop at Laravel 12 or go straight to 13.
- Laravel 10 end of life: your upgrade optionsFour routes off Laravel 10, and the breaking changes in the first step.
- How much does a Laravel upgrade cost?Our published prices by application size, and what moves a quote.
- Upgrading from Laravel 12 to 13The changes that matter, in the order we would check them.
- PHP 8.1 end of life and LaravelWhy PHP can move before the framework does.
- Laravel upgrade checklistEvery step from inventory to the first week after release.
- Laravel vs Symfony: an upgrade decisionSupport windows compared, and when changing framework makes sense.
Upgrading from Laravel 11?
Send us your repository or composer.json. We’ll tell you if going straight to 13 is realistic, and give you a fixed price.
We reply within one business day (IST).