esedark
Server racks representing a distributed worker architecture

rabbitmq / workers / retries / observability

RabbitMQ for bot automation: a practical architecture

A broker does not make unreliable automation reliable by itself. Reliability comes from message contracts, acknowledgements, idempotent workers and visible failure paths.

RabbitMQ is useful when a controller must distribute independent jobs across browser, Android, integration or data-processing workers. It decouples job creation from execution and provides backpressure, routing and acknowledgements. It does not replace the database that stores business state.

A simple production topology

The API validates a request, writes the job record to the database and publishes a compact message containing job ID, task type, tenant or account reference, priority and schema version. A durable topic exchange routes it to queues by capability: for example Android, browser or enrichment.

Workers fetch a limited number of messages, load current state from the database, acquire any required resource lease and execute the task. They acknowledge only after the durable result is stored. This extends the principles in designing work queues for mobile bots.

Assume at-least-once delivery

A worker may complete a side effect and crash before acknowledgement, so RabbitMQ can deliver the message again. Make operations idempotent: assign a stable operation key, check completed state before execution and use database constraints or remote idempotency support where available.

Do not acknowledge at the start. Do not use infinite requeue loops either. Classify failures as transient, permanent or uncertain. An uncertain result requires reconciliation before another external action.

Retries and dead letters

Use bounded retry queues with increasing delays, commonly through dead-letter routing or the delayed-message mechanism if it is approved in your environment. Store attempt count and last error category. After the final attempt, route the job to a dead-letter queue and mark it for operator review.

Authentication failures, invalid input and policy restrictions are usually not retryable. Network timeouts, temporary service errors and unavailable devices may be retryable. Add jitter so a recovered dependency is not hit by every worker simultaneously.

Control concurrency around real resources

Queue depth is not a licence to start unlimited workers. Set prefetch according to task duration and memory use. Keep one active lease per constrained phone, browser profile or account where parallel actions would conflict. Apply per-service and per-account rate limits outside RabbitMQ.

Use heartbeats, connection recovery and publisher confirms. Quorum queues are appropriate when queue availability and data safety justify their operational cost; choose deliberately based on RabbitMQ's current supported configuration and test node failures before production.

Make the system observable

Monitor ready and unacknowledged messages, oldest-job age, publish and completion rates, retry counts, dead letters, worker capacity and end-to-end latency. Propagate a correlation ID from API to message, worker log and result. Never place credentials, session tokens or large page payloads in messages.

Combine broker metrics with application logs described in what to store in bot logs. A healthy queue can still hide workers producing incorrect business outcomes.

Common mistakes

  • using RabbitMQ as the source of truth
  • putting large files or secrets inside messages
  • acknowledging before persisting the result
  • assuming exactly-once execution
  • requeueing every error forever
  • sharing one queue between incompatible worker capabilities
  • ignoring prefetch and resource leases
  • deploying without publisher confirms or dead-letter review
  • monitoring queue size but not job age and outcomes

Practical checklist

  • define a versioned, minimal message schema
  • store business state in a database
  • use durable queues and persistent messages where required
  • enable publisher confirms and manual acknowledgements
  • make every external operation idempotent or reconcilable
  • classify errors and bound retries
  • configure dead-letter routing and operator replay
  • set prefetch, worker limits and resource leases
  • propagate correlation IDs and safe structured logs
  • test worker crashes, broker restarts and dependency outages

When hiring a technical person makes sense

Hire a specialist when jobs trigger paid or irreversible actions, multiple worker types share scarce devices, tenants need isolation or queues must survive node failures. The hard work is defining state, delivery semantics, reconciliation and operations—not installing RabbitMQ.

Final takeaway

RabbitMQ is a strong coordinator when messages describe work rather than contain the whole system. Keep workers idempotent, retries finite and failures visible. If you need a production automation architecture that can recover safely, see my technical services or contact me.