Skip to content

perf(horizon): skip queues for platforms that are disabled - #321

Merged
paulocastellano merged 11 commits into
trypostit:mainfrom
maciejdzierzek:perf/horizon-skip-disabled-platforms
Sep 3, 2026
Merged

perf(horizon): skip queues for platforms that are disabled#321
paulocastellano merged 11 commits into
trypostit:mainfrom
maciejdzierzek:perf/horizon-skip-disabled-platforms

Conversation

@maciejdzierzek

Copy link
Copy Markdown
Contributor

The social-publishing supervisor listens on Platform::allQueues(), which maps over every enum case regardless of the per-platform *_ENABLED toggles that already exist in config/trypost.php. Combined with minProcesses => 1, that gives one worker per supported platform — including the ones an installation never connects.

On a single-workspace self-host publishing to three networks, that was 19 Horizon workers at roughly 75 MB each. After filtering by the toggles: 9 workers, container memory 1.66 GB → 1.06 GB, with no change in publishing behaviour. On a memory-billed host that is real money for idle workers.

One subtlety worth flagging in review

The filter reads env() directly instead of calling the existing Platform::isEnabled(). That is deliberate, and I got it wrong the first time:

isEnabled() reads config(trypost.platforms.*.enabled), but config files load alphabeticallyhorizon.php is evaluated before trypost.php exists in the repository. So isEnabled() falls back to its default of true and the filter silently becomes a no-op.

It is an easy one to miss, because it only manifests at config:cache time. Calling Platform::allQueues() in tinker afterwards returns the correctly filtered list while the cached config still holds all 14 queues — which is exactly the confusing state I debugged through.

If you would rather keep the logic on the enum, it would need its own env-reading path rather than going through config().

Behaviour

  • Default unchanged: a platform with no *_ENABLED set stays enabled (env(..., true)).
  • Disabling a platform stops provisioning its worker; queued jobs for it are unaffected because nothing enqueues to a disabled platform.

Running in production since 2026-08-31.

maciejdzierzek and others added 11 commits August 31, 2026 21:29
The social-publishing supervisor listens on Platform::allQueues(), which maps
over every enum case regardless of the per-platform *_ENABLED toggles. With
minProcesses => 1 that means one worker per supported platform - even on an
installation that only ever connects two or three of them.

On a single-workspace self-host that was 19 Horizon workers at roughly 75 MB
each; filtering by the toggles brought it to 9 and cut container memory from
1.66 GB to 1.06 GB, with no change in publishing behaviour.

Note on the implementation: the filter reads env() directly rather than calling
Platform::isEnabled(). Config files load alphabetically, so config('trypost.*')
does not exist yet while horizon.php is evaluated - isEnabled() would silently
return its default of true and the filter would be a no-op. This bites at
config:cache time, so it is invisible in tinker.
Move queue filtering to Platform::enabledQueues() and apply it from
AppServiceProvider after config has loaded, avoiding env() parsing in
horizon.php while keeping isEnabled() as the single source of truth.
Remove AppServiceProvider boot override and let isEnabled() fall back
to env when trypost config is not loaded yet.
shouldBeStrict() in production would throw on lazy loads in queued
publish jobs and can stop posting. Restore the Laravel default.
@paulocastellano

paulocastellano commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

@maciejdzierzek

Thanks for this — you were right, it was a real problem (idle Horizon workers for platforms nobody uses).

We just cleaned up the implementation a bit (moved the filter onto Platform::enabledQueues() / isEnabled() instead of parsing env keys in horizon.php), but the idea is yours.

Merging shortly.

@paulocastellano
paulocastellano merged commit ca497e1 into trypostit:main Sep 3, 2026
5 checks passed
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