What's New in Laravel 13.18
Laravel 13.18.0 ships a focused set of improvements across the queue worker, scheduler, Artisan dev commands, and Number helpers, alongside a batch of targeted bug fixes.
Worker Metrics on the WorkerStopping Event
The WorkerStopping event now exposes two new properties that describe what a worker did before it shut down:
jobsProcessed(int|null) — the total number of jobs the worker handled during its lifetime.lastJobProcessedAt(int|float|null) — a microtime timestamp of the last job processed, ornullif the worker stopped before processing anything.
use Illuminate\Queue\Events\WorkerStopping;
Event::listen(function (WorkerStopping $event) {
$event->jobsProcessed; // int|null
$event->lastJobProcessedAt; // int|float|null (microtime)
});
Both values are populated whether the worker exits normally or is killed. This gives you a clean hook to record per-worker throughput or emit metrics to an observability platform when a daemon exits, without instrumenting the job loop yourself.
Graceful Shutdown for schedule:work
schedule:work now catches SIGINT, SIGTERM, and SIGQUIT. On receiving one of these signals it stops scheduling new runs and waits for any in-progress schedule:run to finish before exiting — mirroring the existing behavior of queue:work.
This is particularly relevant in container environments like Kubernetes, where pods receive SIGTERM on shutdown. Previously, that signal could interrupt a task mid-execution.
PR: #60616
Priority-Based Dev Command Registration
Dev commands registered for artisan dev now carry a source priority: userland application commands win over vendor package commands, which win over framework defaults — regardless of service provider boot order.
use Illuminate\Foundation\Console\DevCommands;
DevCommands::artisan('reverb:start --host="0.0.0.0"', 'reverb');
This replaces the previous vendor auto-registration blocker approach with explicit priority, so your overrides always take effect. Additionally, artisan dev now runs with --kill-others-on-fail, meaning if one process in the group fails, the rest are stopped rather than left running.
Number Helpers Hardened Against INF and NAN
Number::forHumans(), Number::abbreviate(), and Number::fileSize() previously threw exceptions when passed INF or NAN. All three are now fixed to handle these edge-case inputs without crashing.
Other Fixes and Improvements
- Reduced unnecessary cache hits when using debounced jobs (#60575)
- Fixed cache headers not being set on HEAD requests (#60589)
- Prevented the
restoredevent from firing when a soft-delete restore fails (#60605) - Fixed
RateLimitedmiddleware not serializingreleaseAfterin__sleep()(#60609) - Fixed
flexible()lock and defer label collisions inTaggedCache(#60626) - Fixed JSON parsing for top-level zero bodies (#60614)
- Added conditional return types and synced getter return types with property generics
Key Takeaways
- Listen to
WorkerStoppingto capture per-worker job counts and last-processed timestamps without custom instrumentation. schedule:worknow handlesSIGTERMgracefully — important for Kubernetes and other container runtimes.- Userland
artisan devcommand registrations always win over vendor and framework defaults via explicit priority. Number::forHumans(),Number::abbreviate(), andNumber::fileSize()no longer crash onINForNANinputs.- Several cache, scheduler, and middleware edge-case bugs are resolved in this release.
Source: Laravel News — Laravel 13.18.0