# RabbitMQ Event Catalog All async communication between services uses RabbitMQ. Events follow strict naming: `{domain}.{entity}.{verb}.v{n}` (past tense). ## Exchanges | Exchange | Type | Purpose | |---------------------------|----------|--------------------------------------| | `flatrender.events` | topic | Domain events (fan-out by routing) | | `flatrender.render` | direct | Render job dispatch (per queue) | | `flatrender.notify` | direct | Notification dispatch (per channel) | | `flatrender.dlq` | fanout | Dead-letter queue | ## Common envelope Every message body has this shape: ```json { "event_id": "uuid", "event_type": "render.job.completed.v1", "event_time": "2026-05-27T10:15:00Z", "tenant_id": "uuid", "user_id": "uuid", "trace_id": "uuid", "correlation_id": "uuid", "producer": "render-orchestrator", "data": { ... } } ``` ## Headers (AMQP) | Header | Required | Notes | |---------------------|----------|------------------------------------------------| | `content-type` | yes | `application/json` | | `content-encoding` | yes | `utf-8` | | `x-event-type` | yes | Same as `event_type` (for routing convenience) | | `x-tenant-id` | yes | For tenant-aware consumers | | `x-trace-id` | yes | Distributed tracing | | `x-retry-count` | optional | Incremented on requeue | | `x-max-retries` | optional | Default 3 | ## Routing keys (topic exchange `flatrender.events`) ``` identity.user.registered.v1 identity.user.email_verified.v1 identity.user.banned.v1 identity.tenant.created.v1 identity.tenant.suspended.v1 identity.plan.activated.v1 identity.plan.expired.v1 identity.payment.succeeded.v1 identity.payment.failed.v1 identity.payment.refunded.v1 identity.api_key.created.v1 identity.api_key.revoked.v1 content.template.published.v1 content.template.unpublished.v1 content.font.installed.v1 content.svg_preview.generated.v1 studio.project.saved.v1 studio.project.deleted.v1 render.job.queued.v1 render.job.started.v1 render.job.progress.v1 render.job.completed.v1 render.job.failed.v1 render.job.cancelled.v1 render.snapshot.requested.v1 render.snapshot.ready.v1 node.online.v1 node.offline.v1 node.crashed.v1 node.heartbeat.v1 node.cache.updated.v1 file.uploaded.v1 file.processed.v1 file.deleted.v1 file.quota_warning.v1 file.quota_exceeded.v1 file.cleanup.scheduled.v1 file.cleanup.executed.v1 notification.created.v1 notification.delivered.v1 notification.failed.v1 tenant.usage.recorded.v1 tenant.webhook.fired.v1 tenant.webhook.failed.v1 ``` ## Render dispatch (direct exchange `flatrender.render`) ``` render.queue.snapshot render.queue.vip render.queue.paid render.queue.preview render.queue.mockup render.queue.voiceover ``` Each queue has priority `x-max-priority: 10`. Job priority encoded in message priority property. ## Notification dispatch (direct exchange `flatrender.notify`) ``` notify.channel.push notify.channel.email notify.channel.sms notify.channel.telegram notify.channel.webhook ``` ## Dead-letter routing Failed messages (after `x-max-retries` exhausted) are republished to `flatrender.dlq` with original routing key preserved in `x-original-routing-key` header.