Skip to content

Platform events

When something changes on the platform — a user registers, is suspended, has roles changed — it’s published as a platform event your application can react to.

  1. The auth API writes the event to a transactional outbox in the same database transaction as the change (so events can never be lost or fabricated relative to the data).
  2. A dispatcher publishes outbox rows to a RabbitMQ topic exchange (arrowlabs.events), using the event type as the routing key.
  3. Each application has its own durable queue, arrowlabs.events.{client_id}, bound to the event types it subscribes to. Your consumer drains that queue.

You consume only — the platform owns the queue and bindings. The SDKs attach to your queue without declaring or binding anything.

Every message is a JSON envelope (snake_case on the wire):

{
"event_id": "",
"event_type": "user.registered",
"event_version": 1,
"occurred_at": "2026-06-20T10:30:00Z",
"organisation_id": "",
"actor_user_id": "",
"data": { /* event-specific payload */ }
}

The SDKs decode this and hand your handler the typed data payload plus the envelope metadata.

Event typePayload highlights
user.registereduser_id, email, display_name, roles
user.profile.updateduser_id, changed_fields, current_profile
user.email.changeduser_id, previous_email, new_email
user.suspended / user.unsuspendeduser_id (+ reason)
user.roles.changeduser_id, previous_roles, current_roles
user.deleteduser_id, deleted_by
user.application_access.granted / .revokeduser_id, application_id
user.signed_inuser_id, client_ip, user_agent, mfa_used, method
user.session.revokeduser_id, session_id, reason
application.suspended / .unsuspended / .deletedapplication_id
  • At-least-once. Redelivery happens (reconnects, partial failures), so make your handlers idempotent. Every envelope’s event_id is a stable dedup key — both SDKs expose a pluggable deduplicator hook.
  • Dead-lettering. If a handler fails (or a message can’t be decoded), it’s dead-lettered rather than retried in a tight loop. Failed events are inspectable and retryable from the admin portal.