Short answer
A job's $timeout sets its maximum duration and takes precedence over the worker's general --timeout; when exceeded, the worker is killed and the attempt fails. Most importantly, retry_after in config/queue.php must exceed every execution timeout by a few seconds to prevent a job from running twice.
Explanation
If a job calls a slow external service and the connection hangs, the worker can be occupied forever, preventing other jobs from running. public int $timeout = 60 sets the job's maximum duration; when exceeded, the worker running it is killed and the attempt fails. If $failOnTimeout = true, the job immediately fails with TimeoutExceededException; otherwise, it is retried until attempts are exhausted, then fails with MaxAttemptsExceededException. The retry_after timeout in config/queue.php must be longer than the job timeout; otherwise, Laravel may release the same job while the first copy is still running.
Code example
class LongRunningTask implements ShouldQueue {
public int $timeout = 120; // Two minutes maximum
}Common mistakes
- Setting retry_after to less than the job execution timeout, causing the job to run hundreds of times in parallel.
Follow-up questions
- How do you configure Supervisor on Linux servers to keep Laravel workers running?
- How does Laravel handle failed jobs, and what are the roles of failed() and Exponential Backoff?