Rabbitmq — destinations/rabbitmq
state_stores:
local:
namespace: hookway
memory: {} # Per process; select Redis or PostgreSQL for shared protection.
# examples/destinations/rabbitmq.yaml
#
# Reference config showing the full RabbitMQ destination option surface.
# One flow fans out to two destinations: a primary exchange with dead-letter
# support and an audit exchange with minimal options.
server:
addr: ":8080"
read_timeout: "5s"
write_timeout: "10s"
idle_timeout: "60s"
shutdown_timeout: "10s"
max_body_bytes: 1048576
# Cap concurrent webhook processing (0 = unlimited).
max_inflight_requests: 256
# Cap concurrent fan-out publishes per request (0 defaults to 8).
fanout_concurrency: 8
destinations:
primary:
type: "rabbitmq"
rabbitmq:
url: "${RABBITMQ_URL}"
exchange: "hookway.webhooks"
exchange_type: "direct"
durable: true
publish_timeout: "5s"
declare_queues: true
# Publish concurrency: pool of confirm channels. Raise if broker
# round-trips become the throughput ceiling.
publisher_channels: 8
# Retry a nacked confirm or a transient publish/connect failure before
# giving up. Defaults shown; omit the whole block to use them.
retry:
max_attempts: 3
initial_backoff: "100ms"
max_backoff: "2s"
# Default queue arguments applied to all queues this destination declares.
# There is no per-publish queue_options override.
queue_defaults:
# Drop stale deliveries after this much time in queue.
# RabbitMQ receives this as x-message-ttl in milliseconds.
message_ttl: "24h"
# Bound queue growth so a broken consumer cannot fill the broker.
max_length: 100000
# Reject new publishes when full so providers retry instead of
# silently discarding older queued messages.
overflow: "reject-publish"
# TLS for amqps:// brokers. Omit entirely for publicly trusted certs
# (e.g. CloudAMQP) — the container ships the system CA bundle.
# tls:
# ca_cert: "/etc/hookway/ca.pem"
# client_cert: "/etc/hookway/tls.crt"
# client_key: "/etc/hookway/tls.key"
# server_name: "rabbitmq.internal"
# insecure_skip_verify: false
dead_letter:
enabled: true
exchange: "hookway.webhooks.dlx"
exchange_type: "direct"
queue: "hookway.webhooks.dlq"
routing_key: "webhooks.dead"
durable: true
create_queue: true
audit:
type: "rabbitmq"
rabbitmq:
url: "${RABBITMQ_URL}"
exchange: "hookway.audit"
exchange_type: "direct"
durable: true
publish_timeout: "5s"
declare_queues: true
publisher_channels: 4
flows:
paddle_billing:
# stop_on_failure publishes routes in order and returns 503 on first failure.
# Use skip_failed when audit/secondary destinations should not block intake.
delivery_failure_policy: "stop_on_failure"
nodes:
- {id: in, type: http_trigger, path: /webhooks/paddle, methods: [POST]}
- {id: rl, type: rate_limit, store: local, rpm: 500, burst: 1000, key_by: source_ip}
- {id: body, type: read_body, max_bytes: 1048576}
- {id: auth, type: auth, scheme: hmac_sha256_ts_colon, secret: "${PADDLE_WEBHOOK_SECRET}", signature_header: Paddle-Signature, timestamp_tolerance: "5m"}
- {id: guard, type: replay_guard, store: local, ttl: "10m", max_entries: 50000}
- {id: env, type: envelope, body_format: json}
# queue_options (primary: message_ttl 72h, max_length 500000,
# dead_letter_routing_key paddle.dead; audit: message_ttl 168h) are not
# publish-node fields.
- {id: out1, type: publish, destination: primary, target: paddle-webhooks, create: true}
- {id: out2, type: publish, destination: audit, target: paddle-audit-webhooks, create: true}
edges: [in>rl, rl>body, body>auth, auth>guard, guard>env, env>out1, env>out2]