Skip to main content

Cloudsoft Zone Build, deploy and scale with practical guides to PHP, Node.js, React, DevOps and AI automation. Explore the guides

Cloudsoft Zone
DevOpsLaravelPHPTutorial

Laravel Horizon production controls: dashboard access, capacity and deployment

Review Laravel Horizon production controls for dashboard authorization, queue isolation, bounded capacity, graceful deployments and useful completion alerts.

Cloudsoft Zone

6 min read

Laravel artwork with Horizon production checkpoints covering dashboard authorization, worker capacity and graceful deployment.
Image: Cloudsoft Zone layout; Laravel / Public domain
In this article

A queue dashboard is useful during an incident, but it can also expose job payloads, customer identifiers and retry controls. Running it on the same host as a public application does not make every application user a queue operator.

This Laravel Horizon production guide reviews operational controls after installation: access policy, capacity boundaries, process replacement and acceptance evidence. It intentionally complements an installation tutorial rather than repeating Composer commands. The target is an application already using Horizon with Redis-backed queues.

Use the installed Horizon version's configuration and documented capabilities. Examples here are policy excerpts, not a replacement for your application's authentication system. Keep the existing authorizations and queue owners explicit.

Horizon access is controlled by network exposure, authenticated application identity and a separate operator authorization gate.
Changing the dashboard path does not replace the authorization decision.

Step 1: Decide who may operate the dashboard

Identify the people who need job diagnostics and retries. Ordinary customers, registered users and support staff without queue duties should not gain access merely because they can sign in. The decision belongs on the server, not in a hidden menu item.

Choose whether the dashboard is available through a VPN, private route or deliberately public HTTPS endpoint. Network restrictions reduce exposure, but an authenticated operator policy remains useful. A renamed dashboard URL is not an access-control boundary.

Keep production configured as production. Horizon's development access behavior differs from its non-local gate policy; using a local environment setting to fix a deployment error can expose the dashboard unintentionally.

Step 2: Define a deny-by-default Horizon gate

Extend the existing HorizonServiceProvider gate method. The following example permits only explicitly configured user identifiers and denies when the allowlist is absent:

PHP
use App\Models\User;
use Illuminate\Support\Facades\Gate;

protected function gate(): void
{
    Gate::define('viewHorizon', function (?User $user): bool {
        if ($user === null) {
            return false;
        }

        $allowed = config('operations.horizon_operator_ids', []);

        return in_array(
            (string) $user->getAuthIdentifier(),
            array_map('strval', $allowed),
            true,
        );
    });
}

Create the operations configuration key deliberately as an array, or connect the gate to the application's existing role/permission policy instead. The allowlist is illustrative; it is not an existing permission shipped by Laravel. An absent or empty list denies everyone.

Ensure the dashboard uses your intended authentication guard and session middleware. A gate cannot authenticate a visitor by itself. Preserve CSRF and session protections rather than adding an insecure dashboard-only login shortcut.

After a policy change, refresh the application's relevant configuration cache and processes through the normal release procedure. Do not record customer payloads or credentials in an access-denial log.

Step 3: Verify both access success and failure

Check four identities: an unauthenticated visitor, a signed-in non-operator, an approved operator and a formerly approved account after revocation. Test the actual dashboard and its internal requests, not only the menu link.

Identity Expected behavior
Visitor without a session Login challenge or denial; no queue data
Signed-in non-operator Authorization denial
Approved queue operator Required dashboard functions work
Revoked operator Access no longer succeeds

A redirect to login is acceptable when your authentication flow uses it. Verify its destination and inspect whether any sensitive response was returned before the redirect. Test direct URLs so a hidden link cannot create a false sense of protection.

Step 4: Make environment and queue ownership explicit

Review the Horizon environment that matches the application's actual environment value. Confirm each internal supervisor's connection, queue list and inherited defaults. A missing production or staging entry can leave consumers absent despite a running outer process.

Separate heavy workloads from interactive work when they need independent budgets. A long media job should not occupy every consumer needed for a user-facing notification. Equally, separating lanes does not justify exceeding the database's connection or the provider's rate limit.

Keep Redis private, authenticate according to the deployment policy and isolate application namespaces. Do not share an undifferentiated Redis namespace across unrelated applications. Review retention for Horizon metadata separately from retained queue and customer data.

Horizon capacity planning measures workload, bounds queue lanes and reviews downstream business effects.
A larger worker count can make database or provider failures worse.

Step 5: Set capacity from evidence

Measure job duration, backlog age, throughput and downstream load before changing the process cap. Include all queue consumers across replicas when budgeting database connections and provider requests.

A useful operating worksheet is specific to a lane:

Text
Queue lane: user-notifications
Measured duration range: record staging and observed production evidence
Maximum concurrent provider calls: set from the provider contract
Database connections per worker: measure the actual process
Graceful completion deadline: derive from bounded job execution
Retry policy: bounded attempts, backoff and a stable effect identity

Do not publish an unmeasured universal worker count as a production recommendation. Automatic balancing reacts to workload within configured limits; it does not guarantee that an external dependency can accept more traffic. Queue order under automatic balancing also does not establish strict priority.

Review the job, Horizon timeout and queue reservation policy together. Their ordering must avoid handing a still-running job to another worker. Set the outer supervisor's stop allowance to accommodate the intended graceful completion window.

Step 6: Replace Horizon deliberately during deployment

Horizon stays alive across web requests. Switching the web release pointer does not update code already loaded into that process. Prepare a compatible release and ensure the operating-system supervisor points at the intended release owner.

After the reviewed activation, use the documented graceful termination command under the application runtime identity:

Shell
cd /srv/example-app/current
php artisan horizon:terminate

This changes process state. Confirm that the outer supervisor is configured to restart the intended Horizon process and that the stop allowance is sufficient. Otherwise graceful termination can leave the application without consumers or kill an in-flight effect prematurely.

Keep old and new job payloads and database schema compatible during replacement. A new release may consume work serialized by the previous one. Removing a job class or changing a payload contract needs a migration strategy, not merely a successful deployment command.

A Horizon deployment prepares compatible code, terminates gracefully and verifies that the restarted process consumes jobs with the new release.
The website switching releases does not automatically refresh Horizon.

Step 7: Accept the replacement through one harmless job

Verify the new process identity, current code generation, expected environment and queue list. Submit one harmless diagnostic job and observe its final effect. A process in RUNNING confirms supervision, not correct application consumption.

Compare queue age and failure rate after activation. If the new code fails jobs, stop further rollout and follow the compatible recovery procedure. Do not clear the queue to hide failed acceptance.

Step 8: Keep alerts useful and sensitive data bounded

Monitor queue wait, job failures and missing business completion. Establish who receives each alert and what action it asks them to take. A dashboard that nobody watches is not an operating plan.

Job payloads and exception traces can contain personal data. Restrict dashboard access, minimize logged context and use deliberate retention. Keep stable non-sensitive identifiers so operators can investigate without exposing the entire payload.

Treat retry controls as business mutations. An operator should check whether an external effect already succeeded before retrying it. Our idempotent Laravel jobs guide explains that boundary. For a wider release review, use the Laravel production checklist or contact Cloudsoft Zone.

Featured image: Cloudsoft Zone technical layout with laravel artwork by Laravel (Public domain). Product mark resized proportionally for identification; no endorsement implied. Layout: CC BY-SA 4.0.

Frequently asked questions

  • Is changing /horizon to a hidden path enough to secure it?

    No. Use authenticated access and an explicit authorization gate, with network restrictions where appropriate. Verify unauthenticated and unauthorized denial.

  • Does automatic balancing prioritize the first queue listed?

    No. Under automatic balancing, the queue order does not create strict priority. Define deliberate lanes and capacity when a workload needs reserved service.

  • Why does Horizon continue running old code after web deployment?

    It is a long-lived process. Use its graceful termination mechanism and a supervisor configured to start the new release, then verify the replacement.

Advertise on CloudSoftZone

Your next customer could start right here.

Introduce your tool, product or business to readers exploring technology.

Advertise with us

Explore placements and request a private quote

Sources

  1. Horizon authorization and deployment — Laravel
  2. Laravel authorization gates — Laravel
  3. Supervisor process lifecycle — Supervisor
  4. Supervisor stop and restart configuration — Supervisor
  5. OWASP access control guidance — OWASP
  6. Redis security guidance — Redis

Comments

No comments yet. Be the first to join the conversation.

Leave a comment

Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.

Never published. Used only to contact you about this comment.

Loading the security check…

Comments are moderated before publication.