A queue worker is the engine at the heart of Proletarian. It is a long-running process that continuously polls a database table for jobs, hands each job off to your handler function, and then archives the completed job — all within a database transaction. You create one withDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/msolli/proletarian/llms.txt
Use this file to discover all available pages before exploring further.
proletarian.worker/create-queue-worker, passing it a javax.sql.DataSource and your handler function, then start it with worker/start!.
The Poll/Run Cycle
Each worker thread operates in a tight loop:- Poll — the thread queries the job table for the next available job whose
process_attime is in the past. - Lock — the row is locked using
SELECT … FOR UPDATE SKIP LOCKED, so no other thread or machine can pick it up. - Run — your handler function is called with the job’s type and payload.
- Archive — on success, the job is deleted from the queue table and inserted into the
archived_jobtable with a:successstatus, both in the same transaction. - Repeat — the thread immediately polls for another job. When the queue is empty, it waits for
:proletarian/polling-interval-msbefore polling again.
Thread Pool and Parallelism
The:proletarian/worker-threads option controls how many worker threads run inside one JVM process. Each thread independently polls the queue and runs jobs, so a worker with worker-threads 4 can process four jobs simultaneously.
Scaling Across Multiple Machines
A queue worker is local to a single JVM process. When you run Proletarian on multiple machines (e.g. in a horizontally scaled deployment), each machine runs its own worker process. The total parallelism for a given queue is:SKIP LOCKED, they can all poll the same queue table concurrently without lock contention — each thread atomically claims a row that no other thread has touched.
Default Queue and Named Queues
If you don’t specify a queue, bothjob/enqueue! and worker/create-queue-worker use the default queue :proletarian/default. All jobs live in the same database table and are differentiated by the queue column.
Named queues let you tune throughput and priority independently:
Creating, Starting, and Stopping a Worker
In production, set
:proletarian/install-jvm-shutdown-hook? to true. Proletarian will register a JVM shutdown hook that calls stop! automatically when the process receives a SIGTERM or SIGINT, giving in-flight jobs a chance to complete before the JVM exits. The default timeout for waiting on in-flight jobs is 10 seconds, configurable via :proletarian/await-termination-timeout-ms.Identifying Workers with queue-worker-id
The :proletarian/queue-worker-id option sets a string identifier for the worker. It is used as the thread-name prefix for all threads in the worker’s pool, making it easy to identify worker threads in stack traces and thread dumps. It is also included in every log event under the :proletarian.worker/queue-worker-id key.
proletarian[:email].
The on-shutdown Callback
The :proletarian/on-shutdown option accepts a zero-argument function that Proletarian calls after the worker has fully shut down. Use it to release resources, emit a final log line, or signal a health-check system.
SKIP LOCKED Semantics
Proletarian uses SELECT … FOR UPDATE SKIP LOCKED when polling for jobs. This PostgreSQL/MySQL feature means:
- A thread only sees rows that are not currently locked by another transaction.
- If two threads poll at the same moment they will each claim a different row — neither blocks waiting for the other.
- There is no need for application-level coordination between threads or machines; the database enforces mutual exclusion.
