Worker Metrics on the WorkerStopping Event in Laravel 13.18
Laravel #Laravel #Queue #Scheduler #Artisan #Laravel 13

Worker Metrics on the WorkerStopping Event in Laravel 13.18

3 min read Mohamed Said Mohamed Said

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, or null if 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.

PRs: #60592 and #60608

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.

PRs: #60580 and #60606

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.

PRs: #60617 and #60625

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 restored event from firing when a soft-delete restore fails (#60605)
  • Fixed RateLimited middleware not serializing releaseAfter in __sleep() (#60609)
  • Fixed flexible() lock and defer label collisions in TaggedCache (#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 WorkerStopping to capture per-worker job counts and last-processed timestamps without custom instrumentation.
  • schedule:work now handles SIGTERM gracefully — important for Kubernetes and other container runtimes.
  • Userland artisan dev command registrations always win over vendor and framework defaults via explicit priority.
  • Number::forHumans(), Number::abbreviate(), and Number::fileSize() no longer crash on INF or NAN inputs.
  • Several cache, scheduler, and middleware edge-case bugs are resolved in this release.

Source: Laravel News — Laravel 13.18.0

Found this useful?

Frequently Asked Questions

3 questions
Q01 What new data does the WorkerStopping event expose in Laravel 13.18?
The WorkerStopping event now includes two properties: `jobsProcessed` (the number of jobs handled during the worker's lifetime) and `lastJobProcessedAt` (a microtime timestamp of the final job processed, or null if no jobs were processed).
Q02 Why does graceful shutdown for schedule:work matter in Kubernetes?
Kubernetes sends SIGTERM to pods during shutdown. Before Laravel 13.18, schedule:work did not catch this signal, so an in-progress scheduled task could be interrupted mid-execution. Now it waits for the current run to finish before exiting.
Q03 How does priority-based dev command registration work in artisan dev?
Commands registered for artisan dev are assigned a priority based on their source: application-level registrations take precedence over vendor package registrations, which take precedence over framework defaults. This ensures your overrides always win regardless of service provider boot order.

Continue reading

More Articles

View all