When we need background jobs in an application, we usually think of Redis, BullMQ, or RabbitMQ.
They're great tools. But they also mean more infrastructure to manage.
What if you're already using PostgreSQL and don't need another service?
There's a simple PostgreSQL feature called SKIP LOCKED that makes this possible.
Let's see how it works.
The problem with background jobs
Imagine you're building an application that sends emails in the background.
You store pending emails in a database table called jobs .
SELECT * FROM jobs WHERE status = 'pending' LIMIT 1 ;
Enter fullscreen mode
Exit fullscreen mode
Simple, right?
But what happens when three workers run this query at the same time?
They might all pick the same job and send the same email three times.
That's definitely not what we want.
Meet SKIP LOCKED
PostgreSQL has a neat solution:
WITH next_job AS ( SELECT id FROM jobs WHERE status = 'pending' ORDER BY created_at , id LIMIT 1 FOR UPDATE SKIP LOCKED ) UPDATE jobs SET status =…