Laravel 13.31 adds interruptible jobs, letting queue workers catch the SIGTERM signal sent during deployments and shut down cleanly instead of aborting a task halfway through. Teams that run long jobs—processing tens of thousands of rows, sending bulk emails, or generating reports—benefit because data stays consistent when a new release rolls out.

Why deployments have been killing jobs

When a new version lands, process managers such as Supervisor, Docker, and Kubernetes tell existing workers to stop by sending SIGTERM, a polite request to terminate. Most workers wait for the current job to finish before exiting. The problem appears when the manager grants only a few seconds to comply. If a job needs minutes, the manager escalates to SIGKILL, killing the process instantly. The job never reaches a consistent state, leaving partially updated records, orphaned files, or duplicate work.

Laravel’s answer: cooperative interruption

Laravel 13.31 introduces a contract named Interruptible that a job class can implement to become aware of the termination request. When SIGTERM arrives, Laravel calls the job’s interrupted() method. The framework does not stop the job automatically; the job must check a flag that Laravel sets and exit on its own. This cooperative model lets developers finish the current loop iteration, roll back partial changes, or write a checkpoint before quitting.

How to make a job interruptible

  1. Implement the contract – add implements Interruptible to the job class definition.
  2. Check the flag inside the work loop – insert a check each iteration to see if the job should stop.
  3. Perform cleanup – in interrupted(), persist any state that will allow the job to resume later, or log the interruption for later analysis.

The biggest trap: don’t use --once

Running the queue worker with php artisan queue:work --once disables signal handling entirely. The worker processes a single job and exits, but it never registers the SIGTERM handler. Consequently, any interruptible job ignores the termination request and is killed mid-process. This pattern shows up in cron-driven containers and one-shot deployments. Fix it by running the daemon mode (php artisan queue:work) whenever you need interruptible jobs.

Watching for interruptions

Laravel fires two events you can hook into:

  • WorkerInterrupted – emitted whenever any worker receives a SIGTERM. Logging this event gives a high-level view of how often deployments interrupt workers.
  • JobInterrupted – emitted only if the current job implements the Interruptible contract. Use this event to trigger job-specific cleanup, such as deleting temporary files or updating a “last processed row” marker.

Listening to these events lets teams build dashboards that show deployment impact and spot jobs that frequently get cut short.

Queue size reporting gets a tweak

The release adds a totalSize() method to the queue manager, returning the total number of pending jobs across all queues. The value is reliable for database-backed and Redis drivers, which report actual counts. Drivers like SQS, Sync, and Beanstalkd still return zero because they don’t expose a count through Laravel’s API. Teams using SQS should keep relying on CloudWatch metrics for queue depth.

What this means for different setups

  • Docker/Kubernetes – the graceful shutdown period can now be used effectively. Extend the termination grace period so jobs have a few seconds to notice the flag and exit cleanly.
  • Supervisor – set stopwaitsecs higher than the time you expect a job to finish after receiving the interrupt flag.
  • Legacy jobs – review any job that runs longer than the manager’s timeout and, where feasible, make it interruptible.

Counter-point: added complexity

The feature does not replace proper timeout configuration. If a job’s loop never checks the interruption flag, the manager will still send SIGKILL. Teams must audit long-running code paths and insert checks at logical breakpoints. Some developers may find the extra boilerplate—implementing a contract and adding flag checks—unappealing for short jobs that already finish within the shutdown window.

Action checklist

  1. Przeszukaj skrypty wdrożeniowe pod kątem flagi --once i zastąp ją trybem daemon w miejscach, gdzie używane są przerwalne zadania.
  2. Zidentyfikuj najdłużej trwające zadania (te, które przetwarzają dziesiątki tysięcy wierszy lub trwają kilka minut) i dodaj do nich kontrakt Interruptible.
  3. Wstaw sprawdzenie flagi wewnątrz każdej iteracji pętli i przenieś wszelki niezbędny kod finalizujący do metody interrupted().
  4. Podepnij listenerów do zdarzeń WorkerInterrupted i JobInterrupted, aby zbierać metryki dotyczące tego, jak często wdrożenia wpływają na przetwarzanie.
  5. W przypadku kolejek Redis lub bazodanowych użyj totalSize() do monitorowania zaległości; w przypadku SQS zachowaj istniejące alarmy CloudWatch.

Traktuj wyłączenia spowodowane wdrożeniami jako skoordynowany krok, a nie nagłe przerwanie procesów. Laravel 13.31 zapewnia spójność danych i łagodzi problemy operacyjne związane z niedokończonymi zadaniami. Kosztem jest niewielki wzrost odpowiedzialności w kodzie, ale zespoły polegające na intensywnym przetwarzaniu w tle zyskują bardziej niezawodne środowisko produkcyjne.