Improve application performance by offloading heavy tasks to queues. Learn how to configure drivers, create job classes, and dispatch background jobs.
Previously in this course, we explored Introduction to Laravel Events and Listeners to decouple our business logic. While events help organize code, they are synchronous by default—the listener runs immediately during the request. Today, we add asynchronous processing to our arsenal, allowing us to move heavy operations into the background to keep our API responses snappy.
In a standard web request, the user waits for the server to finish every operation before receiving a response. If your project board API needs to generate a PDF report, send an email notification, or process a large image upload, the user is stuck staring at a loading spinner.
By using queues, we capture these tasks as "jobs" and store them in a database or a service like Redis. A background worker process picks these jobs up and executes them independently of the main request. This is the secret to scaling API design for asynchronous processing and maintaining low latency.
Laravel abstracts the queue system through the QUEUE_CONNECTION setting in your .env file. For development, the sync driver is the default, which executes jobs immediately (blocking the request).
To move to true background processing, you should switch to database or redis. For our project board, let's use the database driver:
php artisan queue:table to create the migration.php artisan migrate to create the jobs table..env: QUEUE_CONNECTION=database.Once configured, any job you dispatch will be inserted into this table, waiting for a worker to process it.
Laravel provides a simple artisan command to generate a job class: php artisan make:job ProcessTaskReport. This creates a class in app/Jobs.
Jobs are essentially plain PHP classes with a handle() method. This is where your heavy lifting resides. Here is how we define a job to handle a task-related report in our project board:
PHPnamespace App\Jobs; use App\Models\Task; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; class ProcessTaskReport implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function __construct(public Task $task) {} public function handle(): void { #6A9955">// Simulate a heavy task, like generating a PDF sleep(5); logger("Report generated for task: {$this->task->id}"); } }
The ShouldQueue interface is the critical piece; it tells Laravel that this class should be handled asynchronously rather than immediately.
You trigger the job from your controller or service layer using the dispatch() method:
PHPpublic function store(Request $request) { $task = Task::create($request->validated()); #6A9955">// Offload the heavy report generation ProcessTaskReport::dispatch($task); return response()->json(['message' => 'Task created, report processing.'], 202); }
SendTaskNotification that accepts a User model.handle() method, use Log::info() to simulate sending an email.TaskService after a task is successfully created.php artisan queue:work in a separate terminal window and create a task via your API. Watch your terminal logs to see the job execute in the background.ShouldQueue Interface: If you omit this, your code will run synchronously, defeating the purpose of using queues.database driver, successful jobs remain in the table. Use php artisan queue:prune to clear out old, completed jobs.SerializesModels. If you delete the model from the database before the job runs, the job will fail. Always ensure your data integrity logic accounts for this, as discussed in Database transactions for data integrity.php artisan queue:work (or a supervisor process), your jobs will sit in the database forever. In production, always use a process monitor like Supervisor or Laravel Horizon.Queues are your primary tool for improving performance in high-load applications. By configuring a driver like database, creating ShouldQueue classes, and dispatching them from your service layer, you decouple the user experience from heavy background work. When implemented alongside reliable background jobs, your application becomes significantly more resilient.
Up next: We will explore how to group these tasks together using Job Chaining and Batching to handle complex, multi-step workflows.
Stop the N+1 query problem in its tracks. Learn how to use eager loading in Laravel to keep your application fast and efficient as your data grows.
Read moreLaravel Queues and Redis Lua scripting provide the foundation for high-throughput architecture. Learn to implement deterministic rate limiting today.
Asynchronous Processing with Queues
Job Chaining and Batching
Feature Testing Fundamentals
Mocking Services and Repositories in Tests
Testing Events and Jobs
Database Factories and Seeding
API Versioning Strategies
Advanced Request Filtering and Sorting
Handling File Uploads in REST APIs
Real-time Notifications with Broadcasting
Using Observers for Model Lifecycle Hooks
Implementing Policies for Authorization
Customizing Authentication Guards
Rate Limiting API Endpoints
Eloquent Performance Optimization
Caching Strategies for Performance
Using Traits for Code Reuse
Advanced Dependency Injection with Service Providers
Command Line Tools with Artisan
Scheduled Tasks and Cron Jobs
Integrating Third-Party Services
Handling Webhooks
Logging and Monitoring
Database Migrations Best Practices
Advanced Testing: Integration Tests
Testing API Authentication
Code Quality and Static Analysis
Project Structure for Large Applications
Environment and Configuration Management
Deploying Laravel Applications
Database Indexing Strategies
Using Value Objects
Strategy Pattern for Business Rules
Advanced Queue Monitoring
Building a Search API
Handling Concurrency and Race Conditions
API Documentation with OpenAPI
Testing with Test Doubles
Implementing Multi-Tenancy
Refactoring Legacy Code
Using Middleware for Feature Flags
Building Reusable Packages
Performance Profiling
Secure API Design
Event Sourcing Concepts