Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

colinlongworth's avatar

Laravel Horizon uses more memory than basic Supervisor setup

I'm trying to work out why my memory usage is considerably higher when I run Horizon vs supervisor directly on Heroku. Horizon is having regular memory exceeded events, versus supervisor which is much more stable.

In the graph, the left-hand side is with Horizon, and the right-hand side with supervisor:

Screenshot of a memory usage.

Horizon Config:

'memory_limit' => 64,

'defaults' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['high', 'default'],
            'balance' => 'auto',
            'autoScalingStrategy' => 'time',
            'maxProcesses' => 1
            'maxTime' => 300,
            'maxJobs' => 100,
            'memory' => 128,
            'tries' => 1,
            'timeout' => 60,
            'nice' => 0,
        ],
    ],

Versus my supervisor.conf set up:

[include]
files = laravel-sync.conf laravel-worker.conf laravel-scheduler.conf
[program:laravel-sync]
process_name=%(program_name)s_%(process_num)02d
command=php artisan queue:work --max-time=180 --max-jobs=100 --queue=high
autostart=true
autorestart=true
numprocs=2
redirect_stderr=true
stdout_logfile=/app/laravel-high-queue.log
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php artisan queue:work --max-time=180 --max-jobs=100 --queue=default
autostart=true
autorestart=true
numprocs=1
redirect_stderr=true
stdout_logfile=/app/laravel-default-queue.log

Note, Laravel Scheduler always runs:

[program:laravel-scheduler]
process_name=%(program_name)s_%(process_num)02d
command=php artisan schedule:work
autostart=true
autorestart=true
numprocs=1
redirect_stderr=true
stdout_logfile=/app/laravel-schedule.log

0 likes
3 replies
LaryAI's avatar
Level 58

The issue you're experiencing with Laravel Horizon consuming more memory compared to a basic Supervisor setup can be attributed to several factors. Here are some steps and considerations to help you diagnose and potentially resolve the issue:

1. Memory Limit Configuration

Ensure that the memory limits are correctly set in your Horizon configuration. You have set 'memory' => 128 in your Horizon config, but you also have a global 'memory_limit' => 64. This could be causing some confusion or conflicts.

2. Process Count and Auto-Scaling

Horizon has an auto-scaling feature that can dynamically adjust the number of worker processes based on the workload. This can sometimes lead to higher memory usage if not properly configured. You might want to disable auto-scaling and manually set the number of processes to see if it stabilizes memory usage.

3. Comparing Configurations

Your Supervisor configuration has numprocs=2 for laravel-sync and numprocs=1 for laravel-worker, which means you have a total of 3 worker processes. In Horizon, you have maxProcesses => 1, which might not be directly comparable. Try to align the number of processes in both configurations for a fair comparison.

4. Horizon's Additional Overhead

Horizon provides a lot of additional features like dashboards, metrics, and auto-scaling, which can add some overhead. If these features are not critical for your use case, you might consider sticking with Supervisor.

5. Optimize Worker Code

Ensure that your worker code is optimized and not holding onto memory unnecessarily. This includes releasing resources, avoiding memory leaks, and using efficient data structures.

Example Adjusted Configuration

Here is an example of how you might adjust your Horizon configuration to better match your Supervisor setup:

// config/horizon.php
'defaults' => [
    'supervisor-1' => [
        'connection' => 'redis',
        'queue' => ['high', 'default'],
        'balance' => 'simple', // Consider using 'simple' instead of 'auto'
        'autoScalingStrategy' => 'time',
        'maxProcesses' => 3, // Match the total number of processes in Supervisor
        'minProcesses' => 3, // Ensure a fixed number of processes
        'maxTime' => 300,
        'maxJobs' => 100,
        'memory' => 128,
        'tries' => 1,
        'timeout' => 60,
        'nice' => 0,
    ],
],

Monitoring and Logging

Enable detailed logging and monitoring to understand where the memory is being consumed. Horizon provides metrics that can help you identify memory usage patterns.

Conclusion

By aligning the number of processes and carefully configuring memory limits, you should be able to achieve more stable memory usage with Horizon. If Horizon's additional features are not necessary, sticking with Supervisor might be a more resource-efficient choice.

If the problem persists, consider profiling your application to identify any memory leaks or inefficiencies in your job processing code.

hybrid1969's avatar

@colinlongworth out of curiosity what did you end up going with, Horizon or laravel-sync and laravel-worker, as I am finding horizon extreamly unstable and prone to just grabbing insane amounts of server resources

colinlongworth's avatar

@hybrid1969 I continued to use Horizon as I the dashboard etc was more valuable. It took a lot of trial and error on Heroku but I eventually got it stable. For Heroku Professional Dynos, the following defaults work for me. I'm not saying they are optinum, but they are the only ones that I could consistently use without crashing the dynos:

[program:laravel-horizon]
process_name=%(program_name)s
command=php artisan horizon
autostart=true
autorestart=true
numprocs=1
redirect_stderr=true
stdout_logfile=/app/laravel-horizon.log
stopwaitsecs=3600

Please or to participate in this conversation.