Architecture
Starting the worker
Run the worker as a standalone process:- Verifies the Redis connection is healthy
- Starts all three worker instances
- Schedules recurring cleanup jobs
- Listens for
SIGTERMandSIGINTfor graceful shutdown
Job Queues
BunShip defines three queues, each with its own configuration:
All queues share a common Redis connection:
Job retention
Completed and failed jobs are pruned automatically:Built-in Workers
Email Worker
Sends transactional emails through Resend. Supports HTML content, plain text, templates, CC/BCC, and reply-to addresses.Webhook Worker
Delivers webhook events to external endpoints with HMAC-SHA256 signing and automatic retries.
Requests time out after 30 seconds. Non-2xx responses trigger a retry with exponential backoff. After all retries are exhausted, the delivery is marked as permanently failed in the database.
Cleanup Worker
Runs maintenance tasks one at a time (concurrency: 1). Four built-in tasks are supported:Creating Custom Workers
Add a new worker by following the existing pattern.1
Define the job data interface and queue
2
Create the worker
3
Register the worker in the startup function
4
Enqueue jobs from your API routes
Job Scheduling
BunShip schedules recurring jobs using BullMQ’s cron repeat feature. These are configured insetupRecurringJobs:
jobId field prevents duplicate recurring jobs when the worker restarts. BullMQ deduplicates by ID, so only one instance of each recurring job exists at a time.
Adding a custom recurring job
Graceful Shutdown
The worker process listens for termination signals and waits for in-progress jobs to finish before exiting:worker.close() stops accepting new jobs and waits for the currently running job to complete. closeQueues() closes all queue connections and the Redis client.
Monitoring and Debugging
Redis health check
The worker verifies the Redis connection on startup:Worker event logging
Each worker emits events for completed, failed, and error states. These are logged to stdout/stderr by default:BullMQ dashboard
For a visual queue dashboard, consider adding Bull Board:Protect the dashboard route with admin-only middleware in production.

