Skip to main content

Cloudsoft Zone Build, deploy and scale with practical guides to PHP, Node.js, React, DevOps and AI automation. Explore the guides

Cloudsoft Zone
Laravel

Upgrading from Laravel 12 to Laravel 13: a practical guide

Laravel 12 lost bug-fix support in August 2026. This guide covers the PHP 8.3 requirement, Composer changes, the CSRF middleware rename, cache and session hardening, low-impact changes that often bite, and a safe rollout plan.

Cloudsoft Zone

8 min read

Plush elePHPant toy from Heroku, a version of the PHP community mascot, photographed close up
Photograph: Atomic Taco from Seattle, WA, USA / CC BY-SA 2.0, via Wikimedia Commons
In this article

Laravel 13 was released on 17 March 2026, and the support clock for Laravel 12 is already running: according to the official support policy, Laravel 12 stopped receiving bug fixes on 13 August 2026 and will receive security fixes only until 24 February 2027. If your application is on Laravel 12, now is a sensible time to plan the upgrade; if it is on Laravel 11 or earlier, it is already outside security support.

The good news is that Laravel 13 was designed as a light upgrade. The official upgrade guide estimates about ten minutes for a typical application, and the release notes say most applications can move without changing much code. The rest of the work is knowing which of the documented changes touch your code, and testing.

This guide walks through the upgrade from Laravel 12 to 13 in a practical order, with the high- and medium-impact changes explained. It is based on the Laravel 13.x release notes and upgrade guide, the laravel/laravel 13.x skeleton and the php.net supported-versions page, all checked on 7 October 2026. At that date the latest framework release was v13.35.0, published on 6 October 2026.

Before you start: check the support timeline

VersionPHPReleasedBug fixes untilSecurity fixes until
Laravel 118.2 - 8.412 March 20243 September 202512 March 2026
Laravel 128.2 - 8.524 February 202513 August 202624 February 2027
Laravel 138.3 - 8.517 March 2026Q3 202717 March 2028

Source: Laravel 13.x release notes, support policy table. Each major release gets 18 months of bug fixes and two years of security fixes.

Step 1: Upgrade PHP first

Laravel 13 requires PHP 8.3 or newer. Laravel 12 ran on PHP 8.2, so applications still on 8.2 must move PHP first. Do this as its own change: upgrade PHP, run your test suite on Laravel 12, deploy, and only then upgrade the framework. Splitting the work makes it much easier to tell which change broke what.

Which PHP version to pick? According to php.net, PHP 8.2 receives security fixes only until 31 December 2026, PHP 8.3 until 31 December 2027, PHP 8.4 until 31 December 2028 and PHP 8.5 until 31 December 2029. Laravel 13 supports 8.3 through 8.5. Unless a dependency holds you back, 8.4 or 8.5 gives the longest runway.

Official PHP logo with lowercase php lettering inside a purple oval
Laravel 13 supports PHP 8.3, 8.4 and 8.5; PHP 8.2 security support ends on 31 December 2026.

Step 2: Update Composer dependencies

The upgrade guide lists these changes to composer.json:

  • laravel/framework to ^13.0
  • laravel/tinker to ^3.0
  • phpunit/phpunit to ^12.0
  • pestphp/pest to ^4.0 (if you use Pest)
  • laravel/boost to ^2.0 (if you use Boost)

Also raise the php constraint to at least ^8.3. Then update and look carefully at what Composer reports:

Shell
composer update
composer outdated --direct

Third-party packages are usually the real bottleneck. If a package has no release supporting illuminate/* version 13, check its repository for an open pull request, consider replacing it, or wait. Do not force-install incompatible versions.

If you create new projects with the Laravel installer, update it too: composer global update laravel/installer, or update Laravel Herd if you use Herd's bundled installer.

Step 3: Handle the high-impact change: request forgery protection

Laravel's CSRF middleware has been renamed from VerifyCsrfToken to PreventRequestForgery, and it now also verifies the request origin using the browser's Sec-Fetch-Site header. The old names, VerifyCsrfToken and ValidateCsrfToken, remain as deprecated aliases, so existing code keeps working, but you should update direct references, especially in tests and route definitions:

PHP
use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;

// Laravel 12
// ->withoutMiddleware([VerifyCsrfToken::class]);

// Laravel 13
->withoutMiddleware([PreventRequestForgery::class]);

Search the codebase for both old class names. After the upgrade, test any flow where forms are submitted from another origin, such as payment-provider callbacks, embedded widgets or forms posted from a separate marketing site. Those are the places where origin checks are most likely to change behaviour, and webhook routes should be excluded from CSRF protection deliberately rather than by accident.

Step 4: Review the medium-impact changes

Cache unserialisation is locked down

The default cache configuration now includes serializable_classes set to false. This hardens cache unserialisation against PHP deserialisation "gadget chain" attacks if your APP_KEY leaks. If your application deliberately stores PHP objects in the cache, list the allowed classes:

PHP
// config/cache.php
'serializable_classes' => [
    App\Data\CachedDashboardStats::class,
],

The better long-term fix is to cache arrays or other plain data instead of objects.

upsert on MySQL and MariaDB needs uniqueBy

Laravel now throws an InvalidArgumentException if upsert() is called with an empty uniqueBy argument, instead of generating invalid SQL. MySQL and MariaDB ignore the value in practice, but the validation still applies. Search for upsert( and make sure each call passes the unique column list.

Step 5: Scan the low-impact changes that often bite

The upgrade guide lists many low-impact changes. These are the ones most likely to matter in ordinary applications:

ChangeWhat to check
Default cache, Redis prefixes and session cookie name now use hyphensIf you relied on framework fallbacks rather than setting CACHE_PREFIX, REDIS_PREFIX and SESSION_COOKIE, set them explicitly to keep existing keys and avoid logging everyone out
New skeleton sets session serialization to jsonSwitching an existing app from php to json invalidates all active sessions; keep php during the upgrade if that is a problem
MySQL DELETE with JOIN, ORDER BY and LIMITThese clauses are now compiled instead of silently ignored, so MySQL may throw a QueryException where it previously ran an unbounded delete
Domain routes take precedence over non-domain routesReview apps with subdomain or catch-all routes
JobAttempted event exposes $exception; QueueBusy renames $connection to $connectionNameUpdate listeners
symfony/polyfill-php85 adds global array_first() and array_last() on PHP below 8.5Conflicts with legacy helpers of the same name; prefer Illuminate\Support\Arr
Default password reset email subject is now "Reset your password"Update tests and translations that assert the old subject
Creating a model instance while that model is booting throws LogicExceptionMove such logic out of boot() methods

Read the full upgrade guide as well; it also covers contract additions that matter only if you maintain custom cache stores, queue drivers or dispatchers.

Step 6: Compare your config with the new skeleton

The upgrade guide recommends reviewing changes in the laravel/laravel repository. Many are optional, but configuration files often gain new options with secure defaults, such as the cache and session settings above. Use GitHub's compare view between the 12.x and 13.x branches, and adopt changes one at a time with a reason for each.

PHP source code in a code editor with coloured syntax highlighting
Most Laravel 12 applications need only small code changes, but tests are what make the upgrade safe.

Step 7: Test and roll out

  1. Run the full test suite and fix failures before anything else. If coverage is thin, add feature tests for login, checkout, forms and any webhooks before you upgrade.
  2. Clear and rebuild caches on each environment: php artisan optimize:clear, then php artisan optimize.
  3. Deploy to staging with production-like data and exercise sessions, queues, scheduled tasks and emails.
  4. Restart long-running processes after deployment (php artisan reload handles queue workers, Reverb and Octane).
  5. Watch error logs closely for the first days after the production release.

Can AI tools do the upgrade?

The upgrade guide points to two automation options. Laravel Shift is a community-maintained service that automates Laravel upgrades. Laravel Boost, Laravel's first-party MCP server, provides a /upgrade-laravel-v13 command for AI coding assistants such as Claude Code, Cursor, OpenCode, Gemini and VS Code; it requires Boost 2.0. Either can save time, but neither replaces reading the diff and running your tests, because only you know which behaviour your users depend on.

What you get in return

Beyond longer support, Laravel 13 adds first-party features described in the release notes, including the Laravel AI SDK for text generation, agents, embeddings and vector stores, JSON:API resources, and semantic and vector search capabilities. None of these is required to upgrade, but they are available once you are on 13.

A simple upgrade plan for a small team

  1. Day 1: create an upgrade branch, raise PHP to 8.3 or newer locally and in CI, and run the tests on Laravel 12.
  2. Day 1: update composer.json, run composer update, and list every package that blocks the upgrade.
  3. Day 2: apply the code changes from Steps 3 to 5, run the suite, and fix failures.
  4. Day 2: deploy to staging and check sessions, queues, scheduled tasks, email and payment callbacks by hand.
  5. Day 3: release to production at a quiet time with a tested rollback plan, which means a database backup and the previous release kept ready to switch back.

Larger applications with many packages may need longer, mostly for waiting on third-party releases, but the order stays the same.

Summary

Upgrade PHP to 8.3 or newer first, then bump the framework and testing packages, rename CSRF middleware references to PreventRequestForgery, review cache serialisation and upsert calls, and check the low-impact list for prefixes, sessions and MySQL deletes. With a working test suite, most Laravel 12 applications can move to 13 in a day. Doing it before Laravel 12's security support ends in February 2027 keeps you on a supported, patched framework.

Frequently asked questions

  • How long does the Laravel 13 upgrade take?

    The official upgrade guide estimates about ten minutes for a typical application. Real projects take longer mainly because of third-party packages, PHP upgrades and testing.

  • Do I have to rename VerifyCsrfToken?

    Not immediately. VerifyCsrfToken and ValidateCsrfToken remain as deprecated aliases, but you should update references to PreventRequestForgery.

  • Will users be logged out after the upgrade?

    Only if session cookie names change or you switch session serialisation from php to json. Set SESSION_COOKIE explicitly and keep php serialisation during the upgrade if that matters.

  • When does Laravel 12 support end?

    Bug fixes ended on 13 August 2026 and security fixes end on 24 February 2027, according to the Laravel support policy.

Advertise on CloudSoftZone

Your next customer could start right here.

Introduce your tool, product or business to readers exploring technology.

Advertise with us

Explore placements and request a private quote

Sources

  1. Upgrade Guide (Laravel 13.x) — Laravel
  2. Release Notes (Laravel 13.x) — Laravel
  3. Supported Versions — The PHP Group
  4. laravel/framework v13.35.0 release — Laravel (GitHub), 2026-10-06
  5. laravel/laravel 13.x composer.json — Laravel (GitHub)

Written with substantial AI assistance. Facts checked against cited sources. Editorial policy.

Comments

No comments yet. Be the first to join the conversation.

Leave a comment

Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.

Never published. Used only to contact you about this comment.

Loading the security check…

Comments are moderated before publication.