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. Scansionare gli script di deployment alla ricerca del flag --once e sostituirlo con la modalità daemon laddove vengono utilizzati job interrompibili.
  2. Identificare i job più lunghi (quelli che toccano decine di migliaia di righe o che girano per diversi minuti) e aggiungere il contract Interruptible.
  3. Inserire un controllo di un flag all'interno di ogni iterazione del ciclo e spostare qualsiasi codice di finalizzazione necessario nel metodo interrupted().
  4. Collegare dei listener a WorkerInterrupted e JobInterrupted per raccogliere metriche su quanto spesso i deployment influenzino l'elaborazione.
  5. Per le code Redis o del database, utilizzare totalSize() per monitorare il backlog; per SQS, mantenere attivi gli allarmi CloudWatch.

Tratta gli shutdown causati dai deployment come un passaggio coordinato piuttosto che come un'interruzione brusca. Laravel 13.31 mantiene la coerenza dei dati e riduce i mal di testa operativi legati ai job incompleti. Il compromesso è un modesto aumento della responsabilità del codice, ma i team che si affidano a un'intensa elaborazione in background ottengono un ambiente di produzione più affidabile.