Laravel 13 was released on Mar 17, 2026. The official release notes list PHP 8.3 through 8.5 support, bug fixes until Q3 2027, and security fixes until Mar 17, 2028.
This is not a rewrite-the-app release. Laravel 13 is about stronger defaults, cleaner first-party APIs, and making AI-native workflows feel like normal Laravel code.
The release notes call out minimal breaking changes. That does not mean upgrade blindly, but it does mean most healthy Laravel 12 apps should start with the official upgrade guide, a dependency audit, and the test suite rather than a migration plan full of rewrites.
Confirm production runs PHP 8.3 or newer.
Upgrade Composer dependencies in a branch.
Run feature tests around queues, auth, billing, file uploads, and scheduled jobs.
Review custom middleware, policies, API resources, and service providers.
The headline is the Laravel AI SDK. It gives Laravel a provider-agnostic way to build agents, text generation, tool calling, embeddings, audio, images, and vector-store workflows without inventing a parallel application structure.
use App\Ai\Agents\SupportAgent;
$response = SupportAgent::make()->prompt(
'Summarize this customer thread and suggest the next reply.'
);
return (string) $response;The important design point is that AI work can live beside the rest of your Laravel code: actions, jobs, policies, resources, notifications, and tests. Do not hide it behind a separate microservice unless the product actually needs that boundary.
A good first AI feature is narrow. Summarize a support thread, classify an uploaded document, generate a draft reply, or search a known knowledge base. Resist the temptation to start with an autonomous agent that can touch billing, users, and production data on day one. Laravel makes it easy to keep the boundary normal: authorize the action, validate the input, queue slow work, and store the result.
final class DraftSupportReply
{
public function handle(Ticket $ticket): string
{
Gate::authorize('reply', $ticket);
return SupportAgent::make()
->withContext($ticket->messages()->latest()->limit(20)->get())
->prompt('Draft a concise support reply with next steps.')
->text();
}
}Laravel 13 also documents semantic search helpers for embedding text and querying vector-similar rows. That matters because many apps need search over tickets, documents, articles, or internal knowledge before they need a full agent.
use Illuminate\Support\Facades\DB;
$documents = DB::table('documents')
->whereVectorSimilarTo('embedding', 'How do I reset my password?')
->limit(10)
->get();The usual workflow is simple: split text into useful chunks, create embeddings when the content is saved, store the vectors beside the source record, then query by meaning when a user asks a question. Keep permissions in the query. A vector result the user is not allowed to read is still a data leak.
$results = DocumentChunk::query()
->where('account_id', $user->account_id)
->whereVectorSimilarTo('embedding', $question)
->limit(8)
->get();JSON:API resources are a good signal for teams building public APIs, mobile backends, or partner integrations. They keep response shape, relationships, links, and metadata closer to Laravel resource conventions instead of scattering API formatting through controllers.
final class ArticleResource extends JsonApiResource
{
public function toAttributes(Request $request): array
{
return [
'title' => $this->title,
'slug' => $this->slug,
'publishedAt' => $this->published_at?->toIso8601String(),
];
}
}The win is contract discipline. Controllers can return resources, resources can own the public shape, and tests can assert one stable response format. That matters when the API is used by a mobile app or external partner that cannot update every time your Eloquent model changes.
Laravel 13 introduces origin-aware request verification through PreventRequestForgery. Treat this as a chance to revisit webhook endpoints, first-party forms, SPA requests, and any cross-origin behavior that has grown organically over time.
Do not apply request verification blindly to webhooks. Stripe, GitHub, Mux, and other providers often need their own signature checks and CSRF exceptions. The upgrade task is to name each boundary clearly: first-party browser requests use Laravel protections; third-party callbacks use provider signatures and narrow route definitions.
Queue routing lets you centralize where job classes should run. That is cleaner than repeating connection and queue decisions across dispatch calls.
use App\Jobs\ProcessPodcast;
use Illuminate\Support\Facades\Queue;
Queue::route(ProcessPodcast::class, connection: 'redis', queue: 'podcasts');The expanded attribute support is useful for code that should be obvious at the class or method boundary. Middleware, authorization, tries, backoff, timeout, and fail-on-timeout configuration can move closer to the thing they affect.
use App\Models\Comment;
use App\Models\Post;
use Illuminate\Routing\Attributes\Controllers\Authorize;
use Illuminate\Routing\Attributes\Controllers\Middleware;
#[Middleware('auth')]
final class CommentController
{
#[Middleware('subscribed')]
#[Authorize('create', [Comment::class, 'post'])]
public function store(Post $post): void
{
// Store the comment.
}
}Attributes are best when they make behavior visible at the boundary. If the configuration is environment-specific, keep it in config. If it is part of what the controller action or job is, putting it on the class or method can be easier to review.
Cache::touch() is small but practical. When a cached value is still good, you can extend its TTL without re-creating the value. That is useful for expensive computed state, warm dashboards, and objects that should stay hot while users keep reading them.
use Illuminate\Support\Facades\Cache;
Cache::touch('dashboard:tenant:42', now()->addMinutes(30));Use this when the value is expensive to rebuild but still correct. Do not use it to hide stale data bugs. If the underlying data changed, forget and rebuild the cache. If the value is still valid and only needs to remain warm, touch is a clean fit.
Composer constraints for Laravel, first-party packages, and PHP 8.3 or newer.
Queue workers, Horizon, and scheduled jobs because Laravel upgrades often reveal stale deployment scripts.
API resource snapshots for any mobile or partner API.
CSRF and request verification behavior around SPAs and webhooks.
Vector database support if the app plans to use semantic search.
AI provider configuration, tool authorization, and logging before exposing AI actions to users.
Keep AI features inside Laravel actions, jobs, and policies until there is a real scaling reason not to.
Use JSON:API resources for external APIs that need a consistent contract.
Route high-volume jobs centrally instead of scattering queue names.
Use vector search first for retrieval, then add agents only where a workflow needs reasoning or tools.
Upgrade with screenshots and real user flows, not just a green composer update.
Laravel 13 feels like a release for applications that have grown up: better AI primitives, better API structure, clearer queue configuration, and enough long-term support runway to make the upgrade worth scheduling now.