Laravel 13 Is Here. Everything That Shipped Today, and Why This Release Hits Different.

Zero breaking changes. PHP 8.3 minimum. PHP Attributes across the framework, passkeys native, the AI SDK stable, Reverb without Redis, Cache::touch(), Teams back in starter kits. March 17, 2026 — the day the Laravel ecosystem aligned.

Taylor Otwell announced it at Laracon EU 2026 and delivered it exactly on schedule: Laravel 13 landed today, March 17, 2026. No dramatic rewrites. No migration nightmares. No late-night composer require that breaks half your app.

What makes this release notable isn’t any single feature. It’s the alignment. Everything the ecosystem has been building toward — the AI SDK, passkeys, WebSockets without Redis, cleaner model configuration, the agentic development story — it all gets its stable release on the same day. Laravel 13 isn’t a maintenance release that happens to drop AI features. It’s the framework catching up to where the ecosystem already was, and making it all official.

Here’s every feature, with working code.


What’s New: The Full Feature List

1. PHP Attributes on Eloquent Models — 9 New Attributes

The headline DX feature. Nine PHP attributes replace the wall of protected $ declarations at the top of every Eloquent model. This is the change you’ll feel immediately on every new model you write.

// BEFORE — Laravel 12
class Invoice extends Model
{
    protected $table      = 'invoices';
    protected $primaryKey = 'invoice_id';
    protected $keyType    = 'string';
    public    $incrementing = false;
    protected $fillable   = ['client_name', 'amount', 'status', 'due_date'];
    protected $hidden     = ['internal_notes', 'cost_price'];
    protected $connection = 'billing';
}
// AFTER — Laravel 13
use Illuminate\Database\Eloquent\Attributes\Table;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Attributes\Connection;

#[Table('invoices', key: 'invoice_id', keyType: 'string', incrementing: false)]
#[Fillable('client_name', 'amount', 'status', 'due_date')]
#[Hidden('internal_notes', 'cost_price')]
#[Connection('billing')]
class Invoice extends Model
{
    protected $casts = [
        'due_date' => 'datetime',
    ];
    // Methods immediately visible — no scrolling past configuration
}

All nine attributes:

AttributeReplaces
#[Table]$table, $primaryKey, $keyType, $incrementing
#[Fillable]$fillable
#[Guarded]$guarded
#[Unguarded](new — no property equivalent)
#[Hidden]$hidden
#[Visible]$visible
#[Appends]$appends
#[Connection]$connection
#[Touches]$touches

Important: Backward compatible. Your existing protected $fillable properties all still work. Nothing breaks. Migrate at your own pace. $casts stays as a property for now — there’s no #[Cast] attribute in this release.

Attributes also work on Artisan commands, listeners, mailables, notifications, and broadcast events:

// Artisan commands
#[Command(signature: 'invoices:send-reminders', description: 'Send payment reminder emails')]
class SendInvoiceReminders extends Command { … }

// Listeners
#[Listen(InvoicePaid::class, queue: 'notifications')]
class SendPaymentConfirmation implements ShouldQueue { … }

// Mailables
#[Mailable(subject: 'Your invoice has been paid')]
class InvoicePaidMail extends Mailable { … }

2. Laravel AI SDK — Now Stable

The laravel/ai package exits beta today, on the same day as Laravel 13. Stable API. Stable agent interface. Production ready.

composer require laravel/ai
php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"
php artisan migrate
// make:agent scaffolds everything
php artisan make:agent InvoiceAnalyst --structured

#[Provider('anthropic')]
#[Temperature(0.2)]
class InvoiceAnalyst implements Agent, HasStructuredOutput
{
    use Promptable;

    public function instructions(): string
    {
        return 'Analyse invoice data and return structured risk assessments.';
    }

    public function tools(): iterable
    {
        return [new GetOverdueInvoices, new WebSearch];
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'risk_level'   => $schema->string()->enum(['low', 'medium', 'high'])->required(),
            'outstanding'  => $schema->number()->required(),
            'action'       => $schema->string()->required(),
        ];
    }
}

// Use it:
$response = (new InvoiceAnalyst)->prompt('Analyse Q1 invoices.');
$risk     = $response['risk_level'];  // 'high'

// Stream it:
return (new InvoiceAnalyst)->stream('Analyse Q1 invoices.');

// Test it (zero API calls):
InvoiceAnalyst::fake();

Six providers out of the box: OpenAI, Anthropic, Gemini, Groq, xAI, Ollama. Provider failover, conversation memory, background queuing, schema-matched testing fakes — all stable.


3. Passkey Authentication — Native in Fortify

WebAuthn-based passwordless authentication is now a first-class Fortify feature. Face ID, Touch ID, Windows Hello, YubiKey — all supported. No third-party packages required.

// config/fortify.php — one line
'features' => [
    Features::registration(),
    Features::resetPasswords(),
    Features::twoFactorAuthentication(),
    Features::passkeys(),   // ← new in Laravel 13
],

New Laravel 13 starter kits scaffold the full passkey flow automatically: passkeys migration, HasPasskeys trait on User, registration and authentication routes, frontend components, and a Security settings page.

What the passkeys table looks like:

passkeys
├── id
├── user_id          → users
├── name             "MacBook Pro", "iPhone 15 Pro"
├── credential_id    WebAuthn credential identifier
├── public_key       stored server-side — the only "secret"
├── sign_count       replay attack prevention
└── timestamps

The private key never leaves the device. The database contains only public keys. A breach exposes nothing useful to an attacker.


4. Reverb Database Driver — No Redis for Real-Time

Horizontal WebSocket scaling without Redis. One environment variable:

# .env
REVERB_SCALING_ENABLED=true
REVERB_SCALING_DRIVER=database   # new in Laravel 13
// config/reverb.php — new driver key
'scaling' => [
    'enabled' => env('REVERB_SCALING_ENABLED', false),
    'driver'  => env('REVERB_SCALING_DRIVER', 'redis'),  // 'redis' | 'database'
    'channel' => 'reverb',
],

Multiple Reverb instances behind a load balancer, coordinated through your existing MySQL or PostgreSQL database. No Redis provisioning. No new service to operate. Your database is already backed up, already monitored, already understood by your team.

Use Redis when you’re already running it for queues/cache — it’s faster at high volume. Use the database driver for everything else.


5. Cache::touch() — Extend TTLs Without Re-Fetching

A small quality-of-life addition that solves a genuinely annoying pattern: extending a cache entry’s expiry without replacing its value.

// BEFORE — fetch, discard, re-store
$value = Cache::get('report:q1');
Cache::put('report:q1', $value, now()->addHour());

// AFTER — Laravel 13
Cache::touch('report:q1', now()->addHour());  // extends TTL, value unchanged

Useful for sliding-window cache strategies — items stay alive as long as they’re being accessed:

// Keep a dashboard widget warm while users are actively viewing it
Cache::touch("dashboard:{$userId}", now()->addMinutes(30));

The default extension is +1 hour if no TTL is passed.


6. Teams in Starter Kits

The multi-tenancy / team model that Jetstream pioneered is back in Laravel 13’s new starter kits — implemented more cleanly and without Jetstream’s overhead.

New starter kit projects can opt into Teams at scaffold time:

laravel new my-saas --using=react
# "Would you like to enable Teams support?" → Yes

What gets scaffolded:

  • teams and team_user pivot tables
  • Team model with HasMembers, HasOwner traits
  • Team creation, invitation, and membership management routes
  • BelongsToTeam trait on User
  • Middleware for scoping requests to the current team
// Scoped to the authenticated user's current team
$invoices = Invoice::where('team_id', $request->user()->currentTeam->id)
    ->with('client')
    ->paginate(20);

SaaS products with multi-tenant requirements no longer need Spark or a manual Teams implementation. It ships with the framework.


Upgrade Guide: From Laravel 12 to 13

Taylor confirmed at Laracon EU: the upgrade is “really smooth and easy.” The official upgrade guide estimates under 10 minutes for most Laravel 12 applications.

The only hard requirement

PHP 8.3 minimum. If you’re on PHP 8.2, upgrade your runtime first — then upgrade Laravel.

php -v  # must be 8.3.x or higher

The upgrade

composer require laravel/framework:^13.0

# Update composer.json
"require": {
    "php": "^8.3",
    "laravel/framework": "^13.0"
}

composer update
php artisan migrate

Four things to check

1. Request forgery protection. Laravel 13 tightens the default CSRF behaviour. Review any routes that skip CSRF verification and confirm they’re intentional.

2. Cache serialization. If you’re caching complex objects with custom serialization, verify they deserialise correctly under the new defaults.

3. Cache and session naming. Default cache prefix behaviour has been updated. Check config/cache.php if you’re relying on auto-generated prefix values.

4. Custom contract implementations. If you’ve bound custom implementations of core framework contracts, review the upgrade guide for any interface changes.

That’s the full list. Most Laravel 12 apps upgrade without touching a single line of application code.


Support Timeline

VersionPHP MinimumBug Fixes UntilSecurity Until
Laravel 12PHP 8.2August 2026February 2027
Laravel 13PHP 8.3Q3 2027Q1 2028

No rush to upgrade today. Laravel 12 is supported through early 2027. But if you’re starting a new project — start on 13.


The Laracon EU Moment Worth Watching

If you missed Laracon EU, watch the closing demo. Taylor added a bug live on stage. Laravel Nightwatch caught it. An AI agent — using the MCP server, the AI SDK, and Laravel Cloud — investigated the error, opened a pull request with the fix, and deployed it. The phone rang. “There’s a PR in your repo — do you want me to merge it?”

He merged it. The bug was fixed. No code was written by hand.

That demo isn’t science fiction. It’s the stack that shipped today: Nightwatch for monitoring, the MCP server for AI agent access, the AI SDK for the agent itself, Cloud CLI for deployment. Every piece is available right now.


What This Release Actually Means

Laravel 13 isn’t the biggest single release in the framework’s history. The features are mostly additive, the upgrade is painless, and the timeline was exactly as announced.

What it is: the release where the framework caught up with where it’s been heading for eighteen months. The AI SDK is stable. Passkeys are native. WebSockets don’t need Redis. The model configuration syntax is cleaner. The agentic stack — MCP, AI SDK, Nightwatch, Cloud — all goes stable on the same day.

You don’t have to use any of it today. Laravel 13 is backward compatible by design. But the direction is clear, and today it has a version number.

Welcome to Laravel 13.


Follow for weekly deep-dives on Laravel, PHP, Vue.js, and the agentic stack.

Leave a Reply

Your email address will not be published. Required fields are marked *