New to Kestra?
Use blueprints to kickstart your first workflows.
Consume RabbitMQ messages in real time with Kestra, validate and forward orders to an API, and automatically dead letter failed or invalid messages.
Give every RabbitMQ order message a traceable, retryable home instead of an opaque consumer process. This blueprint streams messages from an orders.queue queue one execution at a time, validates each payload, forwards valid orders to a downstream API, and republishes anything that fails, whether from bad data or a failed API call, to a dead letter exchange it provisions on its own. No message is ever silently dropped or left stuck at the head of the queue.
io.kestra.plugin.amqp.RealtimeTrigger (on_new_order) opens a manual-ack subscription on the orders.queue queue with serdeType: JSON, launching one execution the moment a message arrives and exposing its deserialized body as trigger.data.declare_dead_letter_exchange (io.kestra.plugin.amqp.DeclareExchange) idempotently declares a FANOUT exchange named orders.dlx.create_dead_letter_queue (io.kestra.plugin.amqp.CreateQueue) idempotently creates the durable orders.dlq queue.bind_dead_letter_queue (io.kestra.plugin.amqp.QueueBind) binds orders.dlq to orders.dlx, so anything published to the exchange lands in the queue. All three provisioning calls are safe to repeat on every execution, since RabbitMQ treats a declare or bind of something that already exists as a no-op.log_order (io.kestra.plugin.core.log.Log) records the raw message for traceability.assert_valid_order (io.kestra.plugin.core.execution.Fail) checks the deserialized payload for order_id and amount; a message missing either field fails the execution immediately instead of reaching the downstream API.process_order (io.kestra.plugin.core.http.Request) POSTs the order to the downstream order processing API; a non-2xx response fails the task the same way an invalid message does.errors block runs publish_to_dead_letter (io.kestra.plugin.amqp.Publish), which republishes the original trigger.data to orders.dlx with a failedExecutionId header, whether the failure came from validation or from the API call.errors block that dead letters both validation failures and API failures.failedExecutionId header on every dead-lettered message, so a person or a follow-up flow can look up exactly which execution rejected it.RabbitMQ can enforce dead-lettering natively with an x-dead-letter-exchange policy, but that keeps failure handling implicit and invisible outside the broker. Kestra's errors block makes the same pattern explicit and observable: every rejected message is tied to a specific execution, with logs, the exact validation or HTTP failure, and a full replay history. The RealtimeTrigger also removes the need to write and operate a long-running consumer process at all, since Kestra manages the subscription, retries, and concurrency for you.
orders.queue queue that upstream producers publish to.RABBITMQ_HOST, RABBITMQ_PORT, RABBITMQ_USERNAME, RABBITMQ_PASSWORD, RABBITMQ_VHOST: broker connection details.ORDERS_API_URL: endpoint of the downstream order processing API.orders.queue exists and something publishes order messages to it (see the produce-to-rabbitmq blueprint for a producer pattern).orders.dlx and orders.dlq and binds them together.amount to orders.queue and confirm it appears in orders.dlq instead of failing silently.process_order so a transient API failure does not immediately dead letter a valid order.FANOUT exchange for a TOPIC exchange with a routing key to split dead letters by failure type.orders.dlq with io.kestra.plugin.amqp.Consume and reprocesses or archives the failed messages.