Laravel 13.10 to 13.15 — Every New Feature Released in June 2026
Most developers upgrade Laravel once — when they do the major version jump. Then they stay on that minor version for months while the framework ships improvements weekly.
Laravel 13.13 itself was released on June 2, 2026, with Bus::bulk() as its headline feature. But to get the full picture, you need to look at all four releases together — 13.10 through 13.13 — because many of the best improvements span the batch. This is the most solid set of queue, cache, and developer experience improvements since Laravel 13 launched. ALM Corp
The Laravel team released v13.15.0 with typed translation accessors, JSON Schema deserialization, a dedicated Cloud queue driver, and a couple of security-related validation and routing fixes. Kamruzzaman Polash
This guide covers every meaningful change from 13.10 through 13.15 — with before/after code for each one.
How to Update First
bash
# Update to latest Laravel 13.x composer update laravel/framework # Verify version php artisan --version # Clear all caches after update php artisan config:cache php artisan route:cache php artisan view:cache
Minor versions in Laravel are safe to update — they never contain breaking changes. Update freely.
1. Bus::bulk() — Dispatch Multiple Jobs in One Call (13.13)
Bus::bulk() is the headline feature of Laravel 13.13, released June 2, 2026. It is the most solid batch of queue improvements since Laravel 13 launched. ALM Corp
The problem it solves:
php
// Before — dispatch in a loop
// N jobs = N separate dispatch calls = N round trips to the queue
foreach ($orders as $order) {
dispatch(new ProcessOrder($order));
}
// For 500 orders — 500 separate queue round trips
// Slow. Inefficient. Gets worse at scale.
After — Bus::bulk():
php
use Illuminate\Support\Facades\Bus;
// All jobs dispatched in one call
Bus::bulk([
new ProcessOrder($order1),
new ProcessOrder($order2),
new SendWelcomeEmail($user1),
new GenerateReport($reportId),
// Mix different job types freely
]);
// With queue and connection specified
Bus::bulk(
collect($orders)->map(fn ($order) => new ProcessOrder($order))->toArray(),
queue: 'high-priority',
connection: 'redis'
);
Real-world use cases:
php
// Import processing — dispatch all at once
public function processImport(array $rows): void
{
$jobs = collect($rows)
->map(fn ($row) => new ProcessImportRow($row))
->toArray();
Bus::bulk($jobs, queue: 'imports');
}
// Order batch processing
public function processPendingOrders(): void
{
$jobs = Order::where('status', 'pending')
->get()
->map(fn ($order) => new ProcessOrder($order))
->toArray();
Bus::bulk($jobs, queue: 'orders', connection: 'redis');
}
// Mixed job types in one bulk dispatch
public function onUserRegistered(User $user): void
{
Bus::bulk([
new SendWelcomeEmail($user),
new CreateDefaultSettings($user),
new NotifyAdminOfNewUser($user),
new SyncToExternalCrm($user),
new GenerateAvatarPlaceholder($user),
]);
}
Performance impact:
For 100 jobs: previously 100 round trips to queue. With Bus::bulk(): 1 round trip. The improvement compounds at scale — batch imports, order processing, notification fans, any high-volume dispatch scenario benefits immediately.
2. Typed Translation Accessors (13.15)
The translation helpers return broad types: __() returns array|string|null, and trans() returns Translator|array|string. Typed trans()->string() and trans()->array() accessors are now available. Kamruzzaman Polash
The problem:
php
// Before — return type is array|string|null
// You had to guess or cast
$message = trans('messages.welcome');
// Is this a string? An array? Null?
// PHPStan complains. IDE has no idea. You cast defensively.
$welcome = (string) trans('messages.welcome'); // defensive cast
$rules = (array) trans('validation.rules'); // defensive cast
After — typed accessors:
php
// Guaranteed string — throws if not a string
$welcome = trans()->string('messages.welcome');
// Guaranteed array — throws if not an array
$rules = trans()->array('validation.rules');
// Practical examples
class UserController extends Controller
{
public function register(): JsonResponse
{
return response()->json([
'message' => trans()->string('auth.registered'),
'next_steps' => trans()->array('onboarding.steps'),
]);
}
}
// In Form Request messages
public function messages(): array
{
return [
'email.required' => trans()->string('validation.email_required'),
'name.required' => trans()->string('validation.name_required'),
];
}
Why this matters:
PHPStan, Psalm, and IDE analysis tools now get accurate type information for translation calls. No more suppression comments. No more defensive casts. Type errors surface at analysis time instead of runtime.
3. Dedicated Cloud Queue Driver (13.15)
A dedicated Cloud queue driver with managed queue handling is now available in Laravel 13.15. Kamruzzaman Polash
If you are deploying on Laravel Cloud, queues previously required manual configuration with Redis or database drivers. The new Cloud driver handles this natively.
Configuration:
php
// config/queue.php
'connections' => [
'cloud' => [
'driver' => 'cloud',
// No host, port, or credentials needed
// Laravel Cloud manages everything
],
// Keep your existing connections for other environments
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
],
],
env
# Production on Laravel Cloud QUEUE_CONNECTION=cloud # Development and staging QUEUE_CONNECTION=redis
Worker setup on Cloud:
bash
# No separate Redis cluster to provision # No queue connection to configure # Just deploy and workers start automatically php artisan queue:work cloud
What managed queue handling means:
- Automatic scaling based on queue depth
- Built-in retry logic at the infrastructure level
- No Redis provisioning, monitoring, or maintenance
- Pay-per-use pricing based on actual queue activity
4. JSON Schema Deserialization — Multi-Type Union Support (13.15)
JSON Schema array deserialization and multi-type union support is now available in Laravel 13.15. Kamruzzaman Polash
Working with external APIs that return varied response structures — sometimes a string, sometimes an array, sometimes null — previously required custom parsing. Laravel 13.15 adds schema-aware deserialization.
php
// Define a schema for an external API response
use Illuminate\Support\JsonSchema;
$schema = JsonSchema::make([
'type' => 'object',
'properties' => [
'user_id' => [
'type' => ['string', 'integer'], // multi-type union
],
'tags' => [
'type' => 'array',
'items' => ['type' => 'string'],
],
'metadata' => [
'type' => ['object', 'null'], // nullable object
],
],
]);
// Deserialize with schema validation
$data = $schema->deserialize($apiResponse->body());
// $data['user_id'] is now properly typed
// $data['tags'] is guaranteed to be an array
// $data['metadata'] is object or null — never unexpected string
Real use case — webhook parsing:
php
class WebhookController extends Controller
{
private JsonSchema $schema;
public function __construct()
{
$this->schema = JsonSchema::make([
'type' => 'object',
'properties' => [
'event' => ['type' => 'string'],
'payload' => ['type' => ['object', 'array']],
'meta' => ['type' => ['object', 'null']],
],
'required' => ['event', 'payload'],
]);
}
public function handle(Request $request): JsonResponse
{
try {
$data = $this->schema->deserialize($request->getContent());
$this->webhookService->process($data);
return response()->json(['received' => true]);
} catch (JsonSchemaException $e) {
return response()->json(['error' => 'Invalid payload'], 400);
}
}
}
5. Tinker MCP Tool — Back as Opt-In
The Tinker MCP tool is back as an opt-in feature. When enabled, agents prefer the MCP tool over the php artisan tinker --execute '...' shell path — skipping the quoting failures that caused agents to retry a simple snippet two or three times. KrishaWeb
This is a developer experience fix with significant practical impact if you use Claude Code or any AI agent with your Laravel project.
The old problem:
bash
# AI agent tries to run a quick Tinker snippet php artisan tinker --execute 'echo User::count();' # Shell quoting issues caused constant failures # Agent retried 2-3 times per simple query # Slowed down entire AI-assisted workflows
With MCP Tinker opt-in:
bash
# Enable in your .claude/mcp.json
{
"servers": {
"laravel-tinker": {
"command": "php",
"args": ["artisan", "mcp:serve"],
"env": {
"APP_ENV": "local"
}
}
}
}
bash
# Enable the feature php artisan tinker:mcp --enable
Now when Claude Code needs to query your database or test a quick expression, it uses the MCP tool directly — no shell quoting, no retries, instant results.
Practical impact for AI-assisted development:
Before: "How many users registered this month?" → Agent tries shell path → Quoting failure → Retry 1 — different quoting → Retry 2 — different approach → Finally works on attempt 3 Total: 45 seconds After: "How many users registered this month?" → Agent uses MCP Tinker tool → Direct PHP execution → Instant result Total: 3 seconds
6. Free Flux Components — Table, Card, Pagination, Toast
Previously, components like table, card, pagination, progress, and toast were listed as Pro-only, causing agents to write custom Blade tables when free alternatives were available. This is now fixed. KrishaWeb
What moved from Flux Pro to Flux Free:
<flux:table>— data tables with sorting<flux:card>— content cards<flux:pagination>— pagination controls<flux:progress>— progress bars<flux:toast>— toast notifications
Before this change:
AI agents and developers checking the Flux docs saw these as Pro-only and wrote custom Blade implementations instead — duplicating work that already existed in the free tier.
After:
html
<!-- Now free — use directly -->
<flux:table>
<flux:table.head>
<flux:table.row>
<flux:table.head.cell>Name</flux:table.head.cell>
<flux:table.head.cell>Email</flux:table.head.cell>
<flux:table.head.cell>Status</flux:table.head.cell>
</flux:table.row>
</flux:table.head>
<flux:table.body>
@foreach ($users as $user)
<flux:table.row>
<flux:table.cell>{{ $user->name }}</flux:table.cell>
<flux:table.cell>{{ $user->email }}</flux:table.cell>
<flux:table.cell>{{ $user->status }}</flux:table.cell>
</flux:table.row>
@endforeach
</flux:table.body>
</flux:table>
<!-- Toast notifications — now free -->
<flux:toast />
<!-- Progress bar — now free -->
<flux:progress value="75" max="100" />
7. Security Fixes — Apply These Immediately (13.15)
A fix for a date_equals validation bypass and tighter route unserialization are included in Laravel 13.15. Kamruzzaman Polash
date_equals validation bypass:
A specific edge case allowed malformed date strings to pass date_equals validation. If your application uses date_equals in any validation rule — update immediately.
php
// Affected rule — update Laravel to patch 'scheduled_at' => ['required', 'date_equals:today'], 'birth_date' => ['required', 'date_equals:' . $user->birth_date], // After updating to 13.15 — properly validated // No code changes needed — just update the framework
Route unserialization:
Tighter controls on what gets deserialized when resolving route model bindings. Relevant if you use custom route binding or have complex model resolution.
Update command:
bash
composer update laravel/framework # Verify 13.15.x in composer.lock
Do not wait on security fixes. These go to production immediately.
8. Laravel Nightwatch — New Monitoring Tool
Laravel Nightwatch is listed alongside Forge, Vapor, Nova, Pulse, and Reverb as a first-party Laravel product in 2026. GitHub
Nightwatch is Laravel's new first-party application monitoring tool — released alongside these minor updates.
What it monitors:
php
// config/nightwatch.php
return [
'token' => env('NIGHTWATCH_TOKEN'),
'monitors' => [
'queries' => true, // Slow query detection
'exceptions' => true, // Exception tracking
'requests' => true, // Request performance
'jobs' => true, // Queue job monitoring
'cache' => true, // Cache hit/miss rates
'schedules' => true, // Scheduled task monitoring
],
// Alert thresholds
'thresholds' => [
'slow_query_ms' => 500,
'slow_request_ms' => 2000,
'error_rate' => 0.01, // 1%
],
];
Think of it as Telescope for production — real-time monitoring, alerts, and performance insights without self-hosting.
9. Laravel Boost — Starter Kit Update
The Boost install command now includes a Laravel Cloud option. KrishaWeb
bash
# New option in Laravel Boost php artisan boost:install # Now includes: # → Standard setup (Forge/VPS) # → Laravel Cloud setup (new) # → Vapor setup (serverless)
Laravel Boost scaffolds your entire deployment configuration — CI/CD pipelines, environment variables, queue workers, scheduler — based on your chosen platform.
Complete Update Summary
VersionReleasedHeadline Feature13.10May 12, 2026Cache improvements13.11May 19, 2026Queue DX improvements13.12May 26, 2026Developer experience batch13.13June 2, 2026Bus::bulk()13.14June 5, 2026 Performance fixes 13.15 June 9, 2026Typed translations, Cloud queue, JSON Schema, Security
Upgrade Checklist
bash
# 1. Update composer update laravel/framework # 2. Verify version php artisan --version # Should show 13.15.x # 3. Clear caches php artisan config:clear php artisan cache:clear php artisan route:clear php artisan view:clear # 4. Rebuild caches for production php artisan config:cache php artisan route:cache php artisan view:cache # 5. Run test suite php artisan test
Apply immediately if you use:
date_equalsvalidation rule — security fix in 13.15- Route model binding with custom resolvers — security fix in 13.15
- Laravel Cloud for deployment — Cloud queue driver in 13.15
Apply when convenient:
Bus::bulk()— refactor high-volume dispatch loops- Typed translation accessors — replace defensive casts
- Tinker MCP — enable if using Claude Code
Wrapping Up
Laravel ships minor releases weekly. Most contain small fixes. This batch — 13.10 through 13.15 — is worth paying attention to specifically because of Bus::bulk(), typed translations, the Cloud queue driver, and the security patches.
The security fixes alone are reason enough to update today. Everything else is a bonus.
Tushar Modi — Full Stack Developer, Jaipur