Mahamudul Hasan Rubel
HomeBlogCoursesAboutProjectsSkillsExperiencePhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • Blog
  • Courses
  • About
  • Projects
  • Skills
  • Experience
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

Subscribe to the newsletter

Get new articles and course lessons delivered to your inbox. No spam, unsubscribe anytime.

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 15 of the Advanced Laravel: Architecture, Scaling & Performance course
LaravelJune 27, 20264 min read

Queue Worker Prioritization: Architecting Laravel Job Hierarchy

Master Laravel queue worker prioritization by implementing named queues. Learn to isolate critical tasks from background jobs for a scalable, responsive system.

LaravelQueuesPerformanceArchitectureScalingphpbackend

Previously in this course, we explored Eloquent Caching Strategies to reduce database load. While caching improves read performance, background processing is the backbone of any high-traffic SaaS. Today, we advance our architecture by implementing Queue Worker Prioritization to ensure your most important domain events aren't stuck behind a massive batch of low-priority emails or report exports.

The Problem: When Everything is Urgent, Nothing Is

By default, Laravel processes jobs in a FIFO (First-In, First-Out) manner on a single default queue. In a production SaaS, this is a recipe for disaster. If a user triggers a batch job that generates 5,000 PDF reports, your critical "Send Password Reset Email" or "Process Payment Callback" jobs might sit in the queue for minutes.

To achieve a production-grade architecture, you must move from a single-queue mindset to a tiered queue hierarchy.

Defining Named Queues

Instead of dispatching every job to the default pipe, categorize your jobs based on their business impact. We typically categorize them into three tiers:

  1. High: Critical path tasks (e.g., payment processing, security alerts, user authentication flows).
  2. Default: Standard application logic (e.g., sending notifications, clearing caches).
  3. Low: Heavy, non-time-sensitive tasks (e.g., analytics processing, report generation, daily cleanup).

You assign a queue to a job using the onQueue() method during dispatch or by defining it in the job class:

PHP
#6A9955">// Dispatching with explicit priority
ProcessPayment::dispatch($order)->onQueue('high');

#6A9955">// Or defining it within the Job class
class GenerateMonthlyReport implements ShouldQueue
{
    public $queue = 'low';
}

Configuring Worker Priority Order

Defining queues is only half the battle. You must instruct your queue:work processes to consume these queues in a specific order. When you start a worker, the order of the queue names matters significantly.

Run the following command on your production server:

Bash
php artisan queue:work --queue=high,default,low

In this configuration, the worker will always check the high queue first. It will only move to the default queue if high is empty. If a new job arrives in high while the worker is busy with a default job, the worker will finish the current job and immediately jump back to the high queue.

Queue Hierarchy Strategy

PriorityQueue NameExamples
P0 (Critical)highPayments, Auth, Security tokens
P1 (Standard)defaultNotifications, Webhooks, Emails
P2 (Background)lowAnalytics, CSV exports, Data pruning

Worked Example: Scaling the SaaS Platform

In our running project, we need to ensure that when a user upgrades their plan, the billing sync is instant, while the "Welcome Email" series can wait a few seconds.

1. Define the Job

PHP
namespace App\Jobs\Billing;

class SyncSubscriptionStatus implements ShouldQueue
{
    public $queue = 'high'; #6A9955">// Always process billing syncs first
    
    public function handle() { #6A9955">/* ... */ }
}

2. Deploy Specialized Workers On a high-traffic system, you shouldn't just rely on one worker command. Use a process manager like Supervisor to run multiple workers with different configurations:

INI
; /etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-worker-high]
command=php /var/www/html/artisan queue:work --queue=high --processes=2

[program:laravel-worker-default]
command=php /var/www/html/artisan queue:work --queue=default,low --processes=4

By dedicating specific processes to the high queue, you guarantee that even if the low queue is flooded with millions of rows of analytics, your billing syncs remain isolated and performant.

Hands-on Exercise

  1. Identify three jobs in your project that are currently in the default queue.
  2. Refactor them into high, default, and low tiers.
  3. Update your local docker-compose.yml or supervisor config to start a worker that prioritizes the high queue.
  4. Verify the order by dispatching a low priority job, then a high priority job, and observing the logs to confirm the high one executes first.

Common Pitfalls

  • Queue Starvation: If you have a poorly optimized high queue that is constantly full, your low queue jobs will never run. Monitor your queue depths using tools like Advanced Queue Monitoring: Mastering Laravel Horizon.
  • Forgetting to update Supervisor: A common mistake is updating the code to use named queues but failing to update the production php artisan queue:work command. The worker will continue to listen only to the default queue, effectively ignoring your new high and low queues.
  • Context Propagation: When moving jobs across queues, ensure you aren't breaking trace context. If you're using observability tools, check Laravel OpenTelemetry Distributed Tracing: Async Queue Context Propagation to ensure your logs remain correlated across the different queues.

Recap

Queue prioritization is about resource isolation. By partitioning your workload into named queues and configuring worker priority, you prevent background noise from degrading the user experience of your critical domain services.

Up next, we will handle Unique Job Patterns to prevent race conditions and duplicate processing for those critical domain events.

Previous lessonEloquent Caching StrategiesNext lesson Unique Job Patterns
Back to Blog

Similar Posts

LaravelJune 28, 20263 min read

Handling Large File Uploads: Streaming to S3 & Async Processing

Master scalable file uploads in Laravel. Learn to stream directly to S3 and process heavy files asynchronously to keep your application fast and memory-efficient.

Read more
LaravelJune 27, 20264 min read

Integrating External Message Brokers: Scaling Laravel Queues

Scale your Laravel infrastructure by moving beyond local Redis queues. Learn to integrate SQS or RabbitMQ for high-scale, durable message processing.

Part of the course

Advanced Laravel: Architecture, Scaling & Performance

advanced · Lesson 15 of 57

  1. 1

    Transitioning from MVC to DDD

    3 min
  2. 2

    Defining Bounded Contexts

    3 min
  3. 3

    Implementing Action Classes

    3 min
Read more
LaravelJune 27, 20264 min read

Read/Write Database Splitting: Scaling Laravel Architecture

Scale your database capacity by offloading heavy read traffic to replicas. Learn how to configure Laravel to automatically route read/write database queries.

Read more
4

Utilizing Data Transfer Objects (DTOs)

3 min
  • 5

    Service Layer Pattern

    4 min
  • 6

    Modular Monolith Structure

    3 min
  • 7

    Querying with Strict Eloquent

    4 min
  • 8

    Advanced Subqueries and Joins

    4 min
  • 9

    Raw Expressions for Performance

    4 min
  • 10

    Advanced Indexing Strategies

    4 min
  • 11

    Database Partitioning Techniques

    4 min
  • 12

    Read/Write Database Splitting

    4 min
  • 13

    Handling Multi-Database Connections

    3 min
  • 14

    Eloquent Caching Strategies

    3 min
  • 15

    Queue Worker Prioritization

    4 min
  • 16

    Unique Job Patterns

    4 min
  • 17

    Rate Limiting Background Jobs

    3 min
  • 18

    Event-Driven Architecture

    4 min
  • 19

    Integrating External Message Brokers

    4 min
  • 20

    Distributed Transactions and Sagas

    3 min
  • 21

    Eventual Consistency Patterns

    4 min
  • 22

    Multi-Layered Caching Strategy

    4 min
  • 23

    Cache Tagging and Invalidation

    4 min
  • 24

    Session Persistence in Clusters

    4 min
  • 25

    High-Availability Infrastructure

    4 min
  • 26

    Zero-Downtime Deployment Pipelines

    4 min
  • 27

    Advanced OAuth2 Implementation

    3 min
  • 28

    JWT and Stateless Security

    4 min
  • 29

    Multi-Tenant Security Isolation

    3 min
  • 30

    Defense Against SSRF

    3 min
  • 31

    Mass Assignment Hardening

    4 min
  • 32

    Automated Security Testing

    3 min
  • 33

    Custom Telemetry Design

    3 min
  • 34

    Distributed Tracing

    4 min
  • 35

    Profiling PHP Execution

    3 min
  • 36

    Memory Management in Long-Running Processes

    4 min
  • 37

    Testing DDD Components

    3 min
  • 38

    Contract Testing

    3 min
  • 39

    Handling Large File Uploads

    3 min
  • 40

    Optimizing Asset Pipelines

    4 min
  • 41

    Database Query Caching Layers

    3 min
  • 42

    Advanced Eloquent Scopes

    4 min
  • 43

    Distributed Locks

    3 min
  • 44

    API Versioning Strategies

    4 min
  • 45

    Database Migration Strategies

    4 min
  • 46

    Handling Webhooks Securely

    3 min
  • 47

    Advanced Logging Patterns

    3 min
  • 48

    Database Indexing for Joins

    4 min
  • 49

    Graceful Degradation

    3 min
  • 50

    Custom Middleware Development

    Coming soon
  • 51

    Database Connection Pooling

    Coming soon
  • 52

    Handling Large Data Exports

    Coming soon
  • 53

    Security Header Configuration

    Coming soon
  • 54

    Database Sharding Concepts

    Coming soon
  • 55

    Real-time Data Synchronization

    Coming soon
  • 56

    Database Deadlock Prevention

    Coming soon
  • 57

    Managing Third-Party API Integrations

    Coming soon
  • View full course