Why Background Processing Matters
Users expect web pages to load in under two seconds. If your controller sends an email, generates a PDF, and pings a webhook before returning a response, you have already lost. Background processing moves heavy work off the request cycle so your application stays fast and your users stay happy.
The pattern is straightforward: your web request creates a lightweight job object that describes the work to be done, pushes it onto a queue, and immediately returns a response to the user. A separate worker process—running in a terminal, a Docker container, or a managed service—picks up jobs from the queue and executes them. The user sees a fast page load, and the heavy lifting happens invisibly in the background.
How Laravel Queues Work
Laravel queues operate on a producer-consumer model. Your application (the producer) serializes job objects—including any Eloquent models they reference—and pushes them onto a queue backend. A queue worker (the consumer) pops jobs off and executes their handle() method. Laravel handles serialization, deserialization, model hydration, and exception handling automatically.
Each job class implements the ShouldQueue interface and uses the Dispatchable, InteractsWithQueue, Queueable, and SerializesModels traits. The SerializesModels trait is particularly clever: instead of serializing the entire model, it stores only the model's ID and class name, then fetches a fresh instance from the database when the worker processes the job. This prevents stale data and keeps serialized payloads small.
Choosing the Right Driver
Database — Zero additional infrastructure. Laravel creates a jobs table and uses it as a queue. Fine for low-volume applications or development environments, but polling the database adds latency and load. Not recommended for production systems processing more than a few hundred jobs per hour.
Redis — Fast, reliable, and feature-rich. Redis queues support delayed jobs, rate limiting, and priority queues natively. The in-memory data store delivers sub-millisecond push and pop operations. For most production Laravel applications, Redis is the sweet spot of performance and simplicity.
Amazon SQS — Fully managed, infinitely scalable, and pay-per-message. SQS eliminates the need to manage Redis infrastructure and scales automatically from zero to millions of messages. Ideal for serverless deployments on Laravel Vapor or applications with unpredictable workloads.
Writing Your First Job
Run php artisan make:job ProcessInvoice to generate a job class. Implement the handle() method with your processing logic. Dispatch it with ProcessInvoice::dispatch($invoice). Laravel serializes the Eloquent model, pushes it to the queue, and the worker hydrates it when processing.
Jobs can accept dependencies via constructor injection and service container resolution in the handle() method. Need a PDF generator? Type-hint it in handle(PdfGenerator $pdf) and Laravel resolves it automatically. This keeps your jobs testable and decoupled from concrete implementations.
Retries, Backoff, and Failure Handling
Set $tries and $backoff properties on the job class to control retry behavior. A job that calls an unreliable third-party API might set $tries = 5 and $backoff = [10, 30, 60, 120, 300] for exponential backoff. Implement the failed() method to notify your team when something goes permanently wrong.
Use php artisan queue:failed to inspect failed jobs. Each entry includes the exception, payload, and queue name. Retry individual jobs with queue:retry or retry all failures at once. For critical workflows, implement a dead-letter queue pattern: after all retries are exhausted, move the job to a separate table for manual review.
Job Batching
Need to process 10,000 CSV rows? Laravel Batch lets you group jobs, track progress, and run a callback when the entire batch completes. Create a batch with Bus::batch([$job1, $job2, ...])->then(fn () => ...)->dispatch(). Monitor batch progress in real time with $batch->progress().
Combine batching with Bus::chain() for sequential multi-step workflows. Import data, validate it, transform it, and generate a report—each step as a separate job, executing in order, with the entire chain failing gracefully if any step throws an exception. This is the kind of workflow orchestration that typically requires dedicated tools like Apache Airflow, built right into Laravel.
Monitoring with Horizon
Laravel Horizon provides a real-time dashboard for Redis queues: throughput, runtime, failure rates, and queue wait times at a glance. Install it, configure your supervisor balance strategy, and sleep better at night. Horizon auto-scales workers across queues based on workload—if your email queue is backed up, Horizon shifts workers from idle queues to clear the backlog.
Set up Horizon notifications to alert your team when wait times exceed a threshold or failure rates spike. Combine with Laravel's notification system to send alerts to Slack, email, or PagerDuty. In production, Horizon is the difference between discovering a queue outage in minutes versus discovering it when a customer complains hours later.
Conclusion
Laravel's queue system transforms your application from a synchronous request-response cycle into an asynchronous, event-driven architecture. Start with the database driver for development, graduate to Redis for production, and add Horizon for monitoring. Your users get fast responses, your infrastructure handles load gracefully, and your team sleeps through the night.
0 Comment