Apicurio Registry change events and the outbox pattern
Apicurio Registry emits change events whenever artifacts, versions, groups, or rules are created, updated, or deleted. These events enable integration with external systems for auditing, automation, and event-driven workflows.
This chapter explains the event system architecture, available event types, and how to configure event delivery for your storage variant:
Overview of Apicurio Registry change events
Apicurio Registry generates structured change events as part of its normal operations. Every time the state of the registry changes, an event is emitted with details about what changed.
Events follow the outbox pattern: they are produced as part of the same transaction that modifies the registry state, guaranteeing that events are consistent with the data. The delivery mechanism depends on which storage variant you use:
-
SQL storage (PostgreSQL, MSSQL): Events are written to an
outboxdatabase table and consumed using Debezium Change Data Capture (CDC). -
KafkaSQL storage: Events are published directly to a dedicated Kafka topic.
Typical use cases for registry events include:
-
Auditing and compliance — Track every change to schemas and API definitions.
-
CI/CD automation — Trigger pipeline runs when a new artifact version is registered.
-
Cache invalidation — Notify downstream services when a schema changes.
-
Event-driven architectures — React to registry state changes in real time.
| Event publishing is supported only with PostgreSQL and MSSQL when using SQL storage. MySQL and H2 do not support the outbox table. KafkaSQL supports events natively. |
Event types reference
Apicurio Registry defines the following event types. Each event includes a JSON payload with details about the change.
Artifact events
| Event type | Description |
|---|---|
|
A new artifact was registered. |
|
An artifact and all its versions were deleted. |
|
An artifact’s name, description, or owner was updated. |
Artifact version events
| Event type | Description |
|---|---|
|
A new version of an artifact was created. |
|
An artifact version was deleted. |
|
A version’s metadata (name, description, labels) was updated. |
|
A version’s lifecycle state changed (for example, from |
Group events
| Event type | Description |
|---|---|
|
A new group was created. |
|
A group was deleted. |
|
A group’s metadata was updated. |
Rule events
| Event type | Description |
|---|---|
|
A global compatibility or validity rule was created, updated, or deleted. |
|
A group-level rule was created, updated, or deleted. |
|
An artifact-level rule was created, updated, or deleted. |
Event payload structure
All events share a common base structure:
{
"id": "<uuid>",
"eventType": "<EVENT_TYPE>",
"groupId": "<group-id>",
"artifactId": "<artifact-id>"
}
Additional fields vary by event type:
-
Version events include a
versionfield. -
State change events include
oldStateandnewStatefields. -
Metadata update events include
name,description, andownerfields where applicable. -
Rule events include
ruleTypeandrule(the rule configuration) fields.
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"eventType": "ARTIFACT_VERSION_CREATED",
"groupId": "com.example",
"artifactId": "my-schema",
"version": "1.2.0",
"name": "My Schema",
"description": "Updated with new fields"
}
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"eventType": "ARTIFACT_VERSION_STATE_CHANGED",
"groupId": "com.example",
"artifactId": "my-schema",
"version": "1.0.0",
"oldState": "ENABLED",
"newState": "DEPRECATED"
}
Event system architecture
The event system uses CDI (Contexts and Dependency Injection) events internally to decouple the storage layer from event delivery. When a storage operation modifies state, it fires a CDI event. A storage-specific event processor observes the CDI event and routes it to the appropriate delivery mechanism.
Event flow
Storage operation (e.g., createArtifact)
|
v
Fire CDI event
(SqlOutboxEvent or KafkaSqlOutboxEvent)
|
+---------------------------+
| |
v v
SQL storage KafkaSQL storage
SqlEventsProcessor KafkaSqlEventsProcessor
| |
v v
Insert into outbox table Publish to Kafka topic
(PostgreSQL / MSSQL) (registry-events)
| |
v |
Debezium CDC connector |
| |
+---------------------------+
|
v
External consumers
(Kafka topic: registry-events)
SQL storage: outbox pattern with Debezium
With SQL storage, events are written to an outbox database table as part of the same database transaction that performs the registry operation. This guarantees that events are only produced for changes that are actually committed.
The outbox table uses an insert-then-delete pattern: the event row is inserted and then immediately deleted within the same transaction. Debezium CDC captures the insert before the deletion takes effect, ensuring the event is published to Kafka without the outbox table growing indefinitely.
The outbox table schema:
CREATE TABLE outbox (
id VARCHAR(128) NOT NULL PRIMARY KEY,
aggregatetype VARCHAR(255) NOT NULL,
aggregateid VARCHAR(255) NOT NULL,
type VARCHAR(255) NOT NULL,
payload JSONB NOT NULL
);
KafkaSQL storage: direct Kafka publishing
With KafkaSQL storage, events bypass the database entirely and are published directly to a dedicated Kafka topic. The events topic uses a single partition to guarantee total ordering of all events. The event’s aggregate ID is used as the Kafka message key.
Configuring events with SQL storage and Debezium
When using SQL storage with PostgreSQL or MSSQL, you can use Debezium to capture events from the outbox table and publish them to Kafka.
-
Apicurio Registry is deployed with SQL storage using PostgreSQL or MSSQL.
-
A Kafka cluster is available.
-
Debezium is deployed with the Kafka Connect framework.
-
Enable logical replication on your PostgreSQL database. Set the following in
postgresql.conf:wal_level = logical -
Create a Debezium PostgreSQL connector that monitors the outbox table. Use the following connector configuration as a starting point:
{ "name": "registry-outbox-connector", "config": { "connector.class": "io.debezium.connector.postgresql.PostgresConnector", "database.hostname": "<database-host>", "database.port": "5432", "database.user": "<database-user>", "database.password": "<database-password>", "database.dbname": "<database-name>", "topic.prefix": "registry", "schema.include.list": "public", "table.include.list": "public.outbox", "transforms": "outbox", "transforms.outbox.type": "io.debezium.transforms.outbox.EventRouter" } } -
Deploy the connector to your Kafka Connect cluster:
curl -X POST http://<kafka-connect-host>:8083/connectors \ -H "Content-Type: application/json" \ -d @connector-config.json -
Verify that events are being published by consuming from the output topic:
kafka-console-consumer --bootstrap-server <kafka-host>:9092 \ --topic outbox.event.registry-events --from-beginning
The Debezium EventRouter transformation reads the outbox table columns and routes events to Kafka topics based on the aggregatetype column.
Configuring events with KafkaSQL storage
When using KafkaSQL storage, events are published directly to a Kafka topic with no additional infrastructure required. The events topic is created automatically when Apicurio Registry starts.
-
Apicurio Registry is deployed with KafkaSQL storage.
-
Optionally configure the events topic name by setting the following environment variable:
APICURIO_EVENTS_KAFKA_TOPIC=registry-eventsThe default topic name is
registry-events. -
Optionally configure topic properties such as replication factor:
APICURIO_EVENTS_KAFKA_TOPIC_REPLICATION_FACTOR=3 -
Consume events from the configured topic:
kafka-console-consumer --bootstrap-server <kafka-host>:9092 \ --topic registry-events --from-beginning
The events topic is configured with the following defaults:
-
Partitions: 1 (single partition for total ordering guarantee)
-
Cleanup policy:
delete -
Retention: Infinite (
-1)
Configuration reference
The following table lists configuration properties related to the Apicurio Registry event system.
| Property | Default | Description |
|---|---|---|
|
|
Name of the Kafka topic used for publishing registry change events. Applies to both SQL (via Debezium) and KafkaSQL storage variants. |
|
Inherited from journal topic |
Replication factor for the events topic (KafkaSQL only). If not set, inherits from the main KafkaSQL journal topic configuration. |
|
|
Cleanup policy for the events topic (KafkaSQL only). |
|
|
Retention time in milliseconds for the events topic (KafkaSQL only). |
Storage variant support
| Storage variant | Events supported | Delivery mechanism | Requirements |
|---|---|---|---|
SQL (PostgreSQL) |
Yes |
Outbox table + Debezium CDC |
Debezium connector, Kafka |
SQL (MSSQL) |
Yes |
Outbox table + Debezium CDC |
Debezium connector, Kafka |
SQL (MySQL) |
No |
— |
— |
SQL (H2) |
No |
— |
— |
KafkaSQL |
Yes |
Direct Kafka publishing |
None (built-in) |
GitOps |
No |
— |
— |
KubernetesOps |
No |
— |
— |
