Message Queues
The Sema Link API uses RabbitMQ for async job dispatch. The API only publishes to queues — it never consumes. Each queue is consumed by a dedicated worker service.
All queues are declared durable on startup. All messages are published with persistent: true so they survive broker restarts.
Queue Reference
| Constant | Queue Name | Publisher | Consumer | Purpose |
|---|---|---|---|---|
SMS_PRIORITY | sms.priority | API | SMS Worker | OTP and transactional messages — high priority lane |
SMS_NORMAL | sms.normal | API | SMS Worker | Standard single sends and due campaign messages |
SMS_CONTENT | sms.content | API | SMS Content Worker | Async content moderation for bulk campaigns |
DLR_INBOUND | dlr.inbound | DLR Webhook Service | DLR Processor Worker | Raw delivery report callbacks from Celcom Africa |
CONTACTS_VALIDATE | contacts.validate | API | Phone Validation Worker | Contact list phone number validation jobs |
Connection Behaviour
The RabbitMQ client (src/queue/client.ts) attempts to connect on startup with up to 5 retries and a 2-second delay between attempts. If the broker is unavailable after all retries, the API continues running but queuing is disabled — publish calls will fail silently for that session.
Publishing
The API publishes via the publishToQueue(queue, payload) helper. Payloads are JSON-serialised. The exact payload shape for each queue is defined by the consuming worker.
Worker Services
Workers are separate Node.js processes — they are not part of the semalink-api repo. See Backend Services for details on each worker's responsibilities and message flow.