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)
| Version | PHP | Released | Bug fixes until | Security until |
|---|---|---|---|---|
| 11 | 8.2–8.4 | Mar 12, 2024 | Sep 3, 2025 | Mar 12, 2026 |
| 12 | 8.2–8.5 | Feb 24, 2025 | Aug 13, 2026 | Feb 24, 2027 |
| 13 | 8.3–8.5 | Mar 17, 2026 | Q3 2027 | Mar 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
$queueproperty 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
VerifyCsrfTokenmiddleware (now formalized asPreventRequestForgery) - 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 situation | Recommendation | Timing |
|---|---|---|
| Greenfield project starting today | Start on Laravel 13 | Now |
| On Laravel 12, active dev team | Plan the upgrade | Next maintenance window |
| On Laravel 12, maintenance mode | Wait for ecosystem to settle | ~Laravel 13.10 or Q3 2026 |
| On Laravel 11 | Upgrade to 12 first, then 13 | Asap — already past security EOL on 11 |
| On Laravel 10 or older | Upgrade incrementally | One major at a time |
| Stuck on PHP 8.2 or below | Upgrade PHP first | Before 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 logic —
PreventRequestForgeryis 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
- Laravel 13 Release Notes (official)
- Laravel 13 Upgrade Guide (official)
- GitHub releases — laravel/framework
- Benjamin Crozat — Laravel 13 release notes
- Laravel News — What We Know About Laravel 13
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.

Comments