Redis looks like the obvious choice for a queue. But why add another service when you already have a database you back up and watch? For most small projects, it is enough.
What you need
A table of jobs and a worker that reads from it. Laravel does this out of the box:
php artisan make:queue-table
php artisan migrate
php artisan queue:work --tries=3
Then switch the driver to database in .env. Nothing else to install.
A job that may run twice
Every job should be safe to run more than once. The worker retries after a failure, so keep it idempotent:
class SendInvoice implements ShouldQueue
{
public int $tries = 3;
public function handle(InvoiceMailer $mailer): void
{
$mailer->sendOnce($this->invoice);
}
}
Where it starts to hurt
The database queue has limits. This is what I measured on a small server:
| Driver | Jobs per second | Latency | Note |
|---|---|---|---|
| database | 120 | 1 s | fine for invoices and emails |
| redis | 2,400 | 5 ms | overkill until you hit the wall |
As long as workers do not wait on a table lock, you have no problem. Once they do, move to Redis.
The switch is boring, which is good. You change the driver and the rest of the code stays the same.
When to move on
- The queue grows faster than workers drain it.
- Jobs must run within a few milliseconds.
- The database is already busy and the queue takes its performance.
If none of that applies, stay on the database. Details are in the Laravel docs, and you can watch the backlog with php artisan queue:monitor.