Skip to content

[12.x] Improve Queues and Horizon documentation #10596

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: 12.x
Choose a base branch
from

Conversation

QuentinGab
Copy link

@QuentinGab QuentinGab commented Jul 11, 2025

About

This PR is based on a recent post I shared on X, where I discussed some pain points around Horizon.

I did my best to avoid injecting strong personal opinions or turning the documentation into a blog post.

Queues:

Clarifies how job attempts are counted and how failed jobs are handled. Adds updated examples and notes for middleware and retries.

Horizon:

Adds sections on queue priorities, job attempts, timeouts, and backoff. Improves explanations for environment configuration and worker balancing.

There are still options left to document.

Reflections on maxException and tries Defaults

While working on this PR, I strongly felt the need for an option to configure maxExceptions at the Horizon supervisor or queue worker level, similar to how tries can currently be set.

Additionally, I’m wondering whether the default value for tries is appropriate. Many of Laravel’s advanced queue features, such as WithoutOverlapping and RateLimited, often require increasing the tries value significantly, sometimes even setting it to 0.

In my opinion, the default configuration should be more aligned with these common use cases. A more sensible default might look like:

  • tries: 25
  • maxException: 1

This defaults would work better out of the box for most Laravel developers .

@@ -1213,7 +1215,21 @@ class ProcessPodcast implements ShouldQueue
<a name="max-attempts"></a>
#### Max Attempts

If one of your queued jobs is encountering an error, you likely do not want it to keep retrying indefinitely. Therefore, Laravel provides various ways to specify how many times or for how long a job may be attempted.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section was confusing to me, as it mixed errors and attempts, so I tried to explain as clearly as possible what an ‘attempt’ is.

Comment on lines +1436 to +1438
> [!NOTE]
> A job marked failed will never be retried.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be redundant, but I added it for people who might not read the entire documentation as they should

horizon.md Outdated
],
```

In this example, jobs in the `high` queue will be prioritized over those in the `default` or `low` queues.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is only the case if balance=false.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I need rewrite this section

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just completely rewritten the section about the strategies.

horizon.md Outdated
@@ -132,7 +176,12 @@ Unlike Laravel's default queue system, Horizon allows you to choose from three w

The `auto` strategy, which is the configuration file's default, adjusts the number of worker processes per queue based on the current workload of the queue. For example, if your `notifications` queue has 1,000 pending jobs while your `render` queue is empty, Horizon will allocate more workers to your `notifications` queue until the queue is empty.

When using the `auto` strategy, you may define the `minProcesses` and `maxProcesses` configuration options to control the minimum number of processes per queue and the maximum number of worker processes in total Horizon should scale up and down to:
When using the auto scaling strategy, you may define the `minProcesses` and `maxProcesses` configuration options:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my testing these work with any balacing mode or at least also with balance=false.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's true, but these options do not have the same meaning. To make more sense of it, I've added the processes key, which is an alias for maxProcesses

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but they work the same regardless of the balancing strategy. So, if you set balance=false, you can still set minProcesses and maxProcesses. If you set minProcesses=1 and maxProcesses=4, 1 process will run in total, even if you have two queues because of balance being set to false. If there is load, Horizon will add up to 3 more workers (total of 4), as it would with any other strategy. This should be reflected somehow, as the current one is confusing to me.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peaklabs-dev Ok, I just realized that I didn't understand the false option correctly. So I guess it was really confusing.

Really appreciate your reviews here! I've updated section about this strategy, let me know if it's sounds good to you.

PS: I’m pretty sure I don’t fully understand the simple one either. From what you’re saying, I’m guessing that Horizon always assigns the same number of processes to each queue when scaling up?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did some testing and it seems that when using the simple strategy, there is no scaling. All worker processes defined by maxProcesses are always running. Let me know if I'm wrong

@QuentinGab QuentinGab marked this pull request as ready for review July 14, 2025 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants