Laravel

Laravel 13 (2026) Release: New Features and Upgrade Guide

Everything you need to know about Laravel 13: new features, breaking changes, and a step-by-step upgrade guide from Laravel 12.

Laravel 13 release banner with new feature highlights

Laravel ships a new major version every year. Laravel 13, released in Q1 2026, continues the framework’s focus on developer experience while pushing toward stricter typing, better performance defaults, and tighter integration with PHP 8.4+ features. Here is what changed, what breaks, and how to upgrade.

What is new in Laravel 13

Typed configuration

Laravel 13 introduces typed configuration retrieval. Instead of guessing whether config('app.debug') returns a string "true" or a boolean, you can now declare expected types:

1
2
3
4
5
6
// config/app.php
return [
'name' => Config::string(env('APP_NAME', 'Laravel')),
'debug' => Config::bool(env('APP_DEBUG', false)),
'port' => Config::int(env('APP_PORT', 8000)),
];

If the value does not match the declared type, Laravel throws a ConfigTypeMismatchException at boot. This catches a class of bugs that previously only surfaced at runtime in specific code paths.

1
2
3
// Accessing typed config
$name = config('app.name'); // guaranteed string
$debug = config('app.debug'); // guaranteed bool

Improved Eloquent performance

The query builder in Laravel 13 uses prepared statement caching by default. Repeated queries with the same structure but different bindings reuse the prepared statement handle, reducing database round-trips.

1
2
3
4
5
6
// This loop now reuses the same prepared statement
foreach ($userIds as $id) {
$user = User::find($id);
// Previously: new prepare + execute each iteration
// Now: prepare once, execute N times
}

Benchmarks show 15-25% improvement on read-heavy workloads with MySQL 8.x and PostgreSQL 16+.

Native enum casting improvements

Eloquent now handles backed enums more gracefully, including nullable enums and enum arrays:

1
2
3
4
5
6
7
8
9
10
11
class Order extends Model
{
protected function casts(): array
{
return [
'status' => OrderStatus::class,
'tags' => AsEnumCollection::of(OrderTag::class),
'priority' => OrderPriority::class, // nullable by default
];
}
}

The AsEnumCollection cast stores an array of enum values in a JSON column and hydrates them back as a typed collection.

Streamlined middleware

Laravel 13 simplifies the middleware stack. The app/Http/Kernel.php file is gone (deprecated since Laravel 11, now removed). All middleware configuration lives in bootstrap/app.php:

1
2
3
4
5
6
return Application::configure(basePath: dirname(__DIR__))
->withMiddleware(function (Middleware $middleware) {
$middleware->append(EnsureJsonResponse::class);
$middleware->trustProxies(at: ['10.0.0.0/8']);
})
->create();

Artisan improvements

New Artisan commands for common tasks:

1
2
3
4
5
6
7
8
# Generate a typed DTO from an existing database table
php artisan make:dto UserData --from-table=users

# Run static analysis as part of artisan
php artisan analyse --level=6

# Show route conflicts
php artisan route:conflicts

The route:conflicts command detects overlapping route definitions that could cause unexpected behavior—a problem that bites teams with large route files.

Breaking changes

PHP 8.4 minimum

Laravel 13 drops support for PHP 8.2 and 8.3. This is the biggest practical impact for most teams. Check your server and CI configuration before attempting the upgrade.

Removed deprecated methods

Methods deprecated in Laravel 11 and 12 are now removed:

  • Route::controller() — use Route::resource() or explicit definitions
  • $request->has() with array syntax — use $request->hasAny()
  • Model::unguard() — use Model::preventSilentlyDiscardingAttributes()
  • Str::slug() with custom separator as second positional arg — use named argument

Queue serialization changes

Job payloads now use a more compact serialization format. Jobs queued by Laravel 12 will fail on a Laravel 13 worker. Drain your queues before deploying the upgrade, or run a mixed worker pool temporarily.

Default pagination

Model::paginate() now returns 25 items per page instead of 15. If your frontend depends on exactly 15 items per page, pass the count explicitly:

1
$users = User::paginate(perPage: 15);

Upgrade guide: Laravel 12 → 13

Step 1: Check PHP version

1
2
php -v
# Must show 8.4.x or higher

Step 2: Update Composer dependencies

1
2
3
4
5
6
{
"require": {
"php": "^8.4",
"laravel/framework": "^13.0"
}
}
1
composer update --with-all-dependencies

Expect dependency resolution conflicts. Common ones:

  • spatie/laravel-permission — needs v7+
  • livewire/livewire — needs v4+
  • inertiajs/inertia-laravel — needs v2+

Step 3: Replace removed methods

Search your codebase for deprecated calls. The Laravel Shift tool can automate this, or do it manually:

1
2
# Find deprecated unguard calls
grep -rn "Model::unguard" app/ database/

Step 4: Update middleware configuration

If you still have app/Http/Kernel.php, move its contents to bootstrap/app.php:

1
2
3
4
5
6
7
8
9
10
11
// Before (Kernel.php)
protected $middleware = [
TrustProxies::class,
HandleCors::class,
];

// After (bootstrap/app.php)
->withMiddleware(function (Middleware $middleware) {
$middleware->trustProxies(at: '*');
$middleware->handleCors();
})

Step 5: Drain queues

Before deploying to production:

1
php artisan queue:drain

Or set QUEUE_CONNECTION=sync temporarily during the deploy window.

Step 6: Run tests

1
php artisan test --parallel

Fix any failures. Common issues:

  • Tests expecting 15-item pagination now get 25
  • Tests using unguard() need updating
  • Tests with serialized job payloads need refreshing

Step 7: Optional — Adopt typed configuration

This is not required for the upgrade but is recommended:

1
2
3
4
5
// Before
'debug' => env('APP_DEBUG', false),

// After
'debug' => Config::bool(env('APP_DEBUG', false)),

Common mistakes during upgrade

Not updating the lock file: Running composer update without --with-all-dependencies leaves transitive dependencies on old versions that may conflict.

Deploying to production without queue drain: Job serialization incompatibility causes silent failures. Workers pick up jobs and crash.

Ignoring deprecation warnings: Laravel 12 emitted deprecation notices for everything removed in 13. If you suppressed those warnings, you now have runtime errors instead.

Testing only the happy path: Edge cases around nullable enum casts and typed config are where subtle bugs hide.

Production tradeoffs

Upgrade now vs. later: If your test coverage is above 70%, upgrade soon to get the performance benefits. If coverage is thin, write tests first.

Laravel Shift vs. manual upgrade: Shift costs $29 per upgrade and handles 80-90% of mechanical changes. For large codebases, the time savings justify the cost.

Typed config adoption: Strongly recommended for new projects, optional for existing ones. The type safety catches real bugs but requires touching every config file.

FAQ

Can I run Laravel 13 on shared hosting?

Only if the host provides PHP 8.4+. Many shared hosts still default to 8.1 or 8.2. Check with your provider.

Is Livewire compatible with Laravel 13?

Livewire v4+ is compatible. Older versions are not. Check the Livewire changelog for specific migration steps.

Should I upgrade from Laravel 10 directly to 13?

No. Go 10 → 11 → 12 → 13. Each step has its own migration path, and skipping versions compounds breaking changes.

Next steps

Start by running php -v on your production server. If you are on PHP 8.4+, create a branch, run composer update, and see what breaks. The test suite will tell you exactly what needs attention.

For developers working with PHP’s broader ecosystem, the PHP 8.5/8.6 new features guide covers language-level changes that Laravel 13 builds on. If you are exploring AI-assisted development, the AI-assisted PHP development guide shows how tools like Copilot can accelerate the upgrade process.