Events and change notifications
Kessel publishes change events whenever resources are created, updated, or deleted. These events enable downstream services to react to changes in real-time, build materialized views, trigger workflows, or maintain synchronized state across distributed systems.
Events are published to Kafka topics with at-least-once delivery guarantees. Each resource write produces events atomically using the transactional outbox pattern, ensuring consistency between database state and published events even in the face of failures or restarts.
This document explains how Kessel’s eventing system works, what events are published, and the delivery guarantees you can rely on.
Event Format
Section titled “Event Format”Kessel events use a JSON structure with fields inspired by CloudEvents attributes, but are not CloudEvents 1.0 compliant. The event structure provides event metadata (type, id, time, subject) and a data field containing the resource payload.
Event envelope fields:
specversion: Always"1.0"(indicates format version)type: Event type in the formatredhat.inventory.resources.{resource_type}.{operation}source: Reserved for future use (currently empty string)id: Unique event identifier (UUID)time: Event timestamp in ISO 8601 formatdatacontenttype: Always"application/json"subject: Resource path (e.g.,/resources/k8s_cluster/{resource_id})data: Event payload (nested object with resource/relationship data)
Example event structure:
{ "specversion": "1.0", "type": "redhat.inventory.resources.k8s_cluster.created", "source": "", "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab", "time": "2026-05-14T15:30:00Z", "datacontenttype": "application/json", "subject": "/resources/k8s_cluster/abc-123", "data": { "metadata": { ... }, "reporter_data": { ... }, "resource_data": { ... } }}This format provides structured event metadata and payload, making it straightforward to route, filter, and process events in downstream consumers.
Event Types
Section titled “Event Types”Kessel publishes resource events when resources are created, updated, or deleted via ReportResource or DeleteResource.
Event type pattern: redhat.inventory.resources.{resource_type}.{operation}
Operations:
created— Resource reported for the first timeupdated— Existing resource representation changeddeleted— Resource marked as deleted (tombstone)
Subject format: /resources/{resource_type}/{resource_id}
Payload structure (data field):
{ "metadata": { "id": "resource-uuid", "resource_type": "k8s_cluster", "org_id": "org-123", "workspace_id": "workspace-456", "created_at": "2026-05-14T10:00:00Z", "updated_at": "2026-05-14T15:30:00Z", "deleted_at": null, "labels": [] }, "reporter_data": { "reporter_type": "acs", "reporter_instance_id": "acs-central-prod", "local_resource_id": "cluster-789", "api_href": "https://acs.example.com/v1/clusters/cluster-789", "console_href": "https://console.redhat.com/openshift/details/cluster-789", "reporter_version": "4.2.1" }, "resource_data": { "name": "production-us-east", "provider": "aws", "region": "us-east-1", "version": "4.15.0" }}Event Topic
Section titled “Event Topic”Resource events are published to the Kafka topic outbox.event.kessel.resources.
Partitioning: Events for the same resource ID are routed to the same Kafka partition (using resource ID as the message key), ensuring ordered processing per resource within a single consumer.
Event Delivery Guarantees
Section titled “Event Delivery Guarantees”Kessel provides reliable event delivery with the following semantics:
At-least-once delivery — Events may be delivered more than once in certain failure scenarios. Consumers should implement idempotent processing to handle duplicate events safely. Kessel’s internal consumer uses OPERATION_TOUCH (upsert) semantics when writing to SpiceDB, ensuring duplicate events do not cause errors.
Atomic publication — Each ReportResource or DeleteResource operation produces events atomically using the transactional outbox pattern. If the write succeeds, the event is guaranteed to be published. If the write fails, no event is published.
Durability — Once an event is published to Kafka, it is durably stored and can be consumed by multiple subscribers independently.
Ordering per resource — Events for the same resource ID are routed to the same Kafka partition, ensuring ordered processing per resource within a single consumer.
These guarantees mean you can rely on the event stream as an authoritative record of all changes without needing to poll the API or implement your own change tracking, as long as your consumer handles duplicate events correctly.
Connection to Consistency Model
Section titled “Connection to Consistency Model”Events and consistency are tightly coupled in Kessel’s architecture. The same event stream that external consumers subscribe to also drives updates to the authorization graph.
How it works:
ReportResourcewrites the resource data- An event is published to the event stream
- Kessel processes the event and updates the authorization graph
- The consistency token is updated upon successful processing
This means the consistency token visible in IMMEDIATE mode checks reflects how far Kessel has progressed through the event stream.
See Consistency model for details on how consistency modes interact with event processing.