A working developer’s decision framework — six weeks after release.


TL;DR

  • Laravel 13 shipped March 17, 2026. Six weeks in. Launch hype is over.
  • Minimum PHP 8.3, supports up to 8.5.
  • No fire to upgrade — Laravel 12 has bug fixes until Aug 2026, security until Feb 2027.
  • The framework team explicitly aimed for minimal breaking changes.
  • Real wins: Queue::route(), expanded PHP attributes, AI SDK (greenfield only).
  • Skip rewriting working code just to use new attribute syntax.
  • The upgrade is small. The regression test pass is the work.

Support Timeline (the only table that matters)

VersionPHPReleasedBug fixes untilSecurity until
118.2–8.4Mar 12, 2024Sep 3, 2025Mar 12, 2026
128.2–8.5Feb 24, 2025Aug 13, 2026Feb 24, 2027
138.3–8.5Mar 17, 2026Q3 2027Mar 17, 2028

Translation:

  • On Laravel 11? Security ended Mar 12, 2026 — you’re already out of support. Move.
  • On Laravel 12? You have ~3.5 months of bug fixes left. Plan the upgrade.
  • On PHP 8.2 or below? Upgrade PHP first, separately, before touching the framework.

The Features, Ranked by Real-World Value

🟢 Worth adopting now

Queue::route() — centralized queue routing

// In a service provider:
Queue::route(ProcessPodcast::class, connection: 'redis', queue: 'podcasts');
Queue::route(SendInvoice::class, connection: 'sqs', queue: 'high-priority');
Queue::route(GenerateReport::class, connection: 'redis', queue: 'reports');
  • Replaces dispatch()->onQueue() scattered across 50 dispatch sites.
  • Replaces $queue property hardcoded in every job class.
  • Migration scenario: switching from Redis to SQS → change one file instead of 20.
  • Adopt immediately if you have 10+ job classes.

Expanded PHP Attributes

// Models
#[Table('users', key: 'user_id', keyType: 'string', incrementing: false)]
#[Fillable(['name', 'email'])]
#[Hidden(['password', 'remember_token'])]
class User extends Model { }

// Controllers
#[Middleware('auth')]
class CommentController
{
    #[Middleware('subscribed')]
    #[Authorize('create', [Comment::class, 'post'])]
    public function store(Post $post) { }
}

// Jobs
#[Tries(3)]
#[Backoff([10, 30, 60])]
#[Timeout(120)]
#[FailOnTimeout]
class ProcessLargeImport implements ShouldQueue { }
  • Optional, fully backwards-compatible.
  • Adopt on new code. Don’t refactor working code just for syntax.
  • Big readability win on jobs — config sits at the top, not buried in properties.

Cache::touch() — extend TTL without re-storing

// Old way:
$value = Cache::get('user:123');
Cache::put('user:123', $value, now()->addHour());

// Laravel 13:
Cache::touch('user:123', now()->addHour());
  • Tiny but useful for session-extension, sliding-window caches, rate-limit refreshes.

🟡 Adopt with caution

Laravel AI SDK

use App\Ai\Agents\SalesCoach;
$response = SalesCoach::make()->prompt('Analyze this transcript...');

use Laravel\Ai\Image;
$image = Image::of('A donut on the kitchen counter')->generate();

use Illuminate\Support\Str;
$embeddings = Str::of('Napa Valley has great wine.')->toEmbeddings();
  • Use on greenfield projects.
  • Don’t rip out working production integrations.
  • Reasons:
    • Provider abstractions only pay off if you actually swap providers.
    • Your existing prompt engineering, retry logic, and cost monitoring already work.
    • “Stable on day one” ≠ “battle-tested in your use case.”
  • Watch for community feedback over the next 3–6 months.

Semantic / Vector Search

$documents = DB::table('documents')
    ->whereVectorSimilarTo('embedding', 'Best wineries in Napa Valley')
    ->limit(10)
    ->get();
  • Clean API. Built on PostgreSQL + pgvector.
  • Not a feature — it’s a project. Requires:
    • PostgreSQL with pgvector extension installed and configured
    • Embedding pipeline (which model? when to re-embed?)
    • Chunking strategy
    • Indexing strategy (HNSW vs IVFFlat)
  • Adopt if you were going to build RAG anyway. Skip otherwise.

JSON:API Resources

  • Native first-party support for the JSON:API spec.
  • Handles sparse fieldsets, relationship inclusion, links, headers.
  • Worth it only if you’re committed to the spec. Don’t migrate a non-JSON:API API just to use this.

🔴 Don’t bother (for now)

  • Rewriting all your existing models to use attributes. Backwards-compatible. Half-attribute / half-property codebases are worse than either alone.
  • Migrating a stable Laravel 12 app this month. No urgency. Plan for the next maintenance window.
  • Adopting the AI SDK in production code that already works. Wait for ecosystem feedback.

Pre-Upgrade Checklist

Run these before you touch composer.json:

1. Verify package compatibility

composer why-not laravel/framework ^13.0

This tells you which packages will block the upgrade. Run for each major package explicitly:

composer why-not livewire/livewire ^3.0
composer why-not filament/filament ^3.0
composer why-not spatie/laravel-permission
composer why-not laravel/sanctum
composer why-not laravel/horizon

2. Check your PHP version

php -v

If 8.2 or below → upgrade PHP first, run the app on 8.3 for 1–2 weeks, then upgrade Laravel. Don’t combine the two upgrades.

3. Audit custom framework integrations

These are the realistic surprise zones — verify each:

  • Custom cache stores or extended Illuminate\Cache\Repository
  • Extended VerifyCsrfToken middleware (now formalized as PreventRequestForgery)
  • Custom queue workers or replaced facades
  • Hand-rolled service container bindings for framework contracts
  • Manually replaced facades anywhere

4. Run your test suite on staging first

  • Full regression pass on staging environment running Laravel 13.
  • Pay specific attention to: queue jobs, auth flows, cache invalidation, scheduled tasks.

The “Should I Upgrade?” Decision Table

Your situationRecommendationTiming
Greenfield project starting todayStart on Laravel 13Now
On Laravel 12, active dev teamPlan the upgradeNext maintenance window
On Laravel 12, maintenance modeWait for ecosystem to settle~Laravel 13.10 or Q3 2026
On Laravel 11Upgrade to 12 first, then 13Asap — already past security EOL on 11
On Laravel 10 or olderUpgrade incrementallyOne major at a time
Stuck on PHP 8.2 or belowUpgrade PHP firstBefore anything else

Realistic Time Budget

For a typical Laravel 12 → 13 upgrade on a production app:

  • Composer dependency resolution: 15–60 minutes (often blocked by one stubborn package)
  • Code changes from upgrade guide: 10–30 minutes
  • Local test suite pass: 1–2 hours
  • Staging regression test: 4–8 hours
  • Production deploy + monitoring: half a day

Total realistic estimate: 1–2 working days for a mature app. The “10-minute upgrade” headline refers to the framework code changes only — not the validation work that should surround them.


What I’m Doing With My Own Projects

  • Next greenfield project: ships on Laravel 13. No reason not to.
  • Existing Laravel 12 apps: stay on 12 through Laravel 13.10 or so. Migrate one at a time during low-traffic windows.
  • AI integrations: keeping existing OpenAI/Claude/local-LLM code as-is. Will use the AI SDK on the next new project.
  • Models / controllers / jobs: adopting PHP attributes on net-new code only. Not refactoring stable code.

The framework team built the release for this exact decision posture. There’s no urgency, only optionality.


Common Gotchas to Watch For

Based on reports from the community upgrade threads and Crozat’s notes:

  • Composer peer-dependency conflicts — most reported issue. Usually one or two packages lag major releases.
  • Custom CSRF logicPreventRequestForgery is more strict about origin. Test cross-origin requests.
  • Cache serialization quirks — if you’ve subclassed cache stores or use custom drivers, regression-test cache hits/misses.
  • Named arguments in Laravel APIs — explicitly NOT covered by the backwards-compat guarantee. Search your codebase for named arguments in framework calls.
  • Queue worker behavior — mostly stable, but worth a regression pass if you have custom worker logic.

Resources


Final Take

  • The upgrade is small, the validation work is the actual work.
  • Plan it. Don’t panic. Don’t rush.
  • Queue::route() alone is reason to start planning if you have queue infrastructure.
  • AI SDK is exciting, but greenfield-first.
  • If anyone tells you it took them 10 minutes start to finish in production — they didn’t run their full test suite.

If you’ve done the upgrade on a real production codebase, drop a comment on what bit you that the release notes didn’t warn about. The post-launch threads are where the actually useful information lives.


Muneeb is a software developer with 8+ years of experience building Laravel applications, AI-integrated systems, and production SaaS. More posts on backend engineering at muneebdev.com.

Categorized in: