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 outbox database 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

Table 1. Artifact event types
Event type Description

ARTIFACT_CREATED

A new artifact was registered.

ARTIFACT_DELETED

An artifact and all its versions were deleted.

ARTIFACT_METADATA_UPDATED

An artifact’s name, description, or owner was updated.

Artifact version events

Table 2. Artifact version event types
Event type Description

ARTIFACT_VERSION_CREATED

A new version of an artifact was created.

ARTIFACT_VERSION_DELETED

An artifact version was deleted.

ARTIFACT_VERSION_METADATA_UPDATED

A version’s metadata (name, description, labels) was updated.

ARTIFACT_VERSION_STATE_CHANGED

A version’s lifecycle state changed (for example, from ENABLED to DEPRECATED).

Group events

Table 3. Group event types
Event type Description

GROUP_CREATED

A new group was created.

GROUP_DELETED

A group was deleted.

GROUP_METADATA_UPDATED

A group’s metadata was updated.

Rule events

Table 4. Rule event types
Event type Description

GLOBAL_RULE_CONFIGURED

A global compatibility or validity rule was created, updated, or deleted.

GROUP_RULE_CONFIGURED

A group-level rule was created, updated, or deleted.

ARTIFACT_RULE_CONFIGURED

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 version field.

  • State change events include oldState and newState fields.

  • Metadata update events include name, description, and owner fields where applicable.

  • Rule events include ruleType and rule (the rule configuration) fields.

Example: ARTIFACT_VERSION_CREATED payload
{
  "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"
}
Example: ARTIFACT_VERSION_STATE_CHANGED payload
{
  "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.

Prerequisites
  • Apicurio Registry is deployed with SQL storage using PostgreSQL or MSSQL.

  • A Kafka cluster is available.

  • Debezium is deployed with the Kafka Connect framework.

Procedure
  1. Enable logical replication on your PostgreSQL database. Set the following in postgresql.conf:

    wal_level = logical
  2. 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"
      }
    }
  3. 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
  4. 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.

Prerequisites
  • Apicurio Registry is deployed with KafkaSQL storage.

Procedure
  1. Optionally configure the events topic name by setting the following environment variable:

    APICURIO_EVENTS_KAFKA_TOPIC=registry-events

    The default topic name is registry-events.

  2. Optionally configure topic properties such as replication factor:

    APICURIO_EVENTS_KAFKA_TOPIC_REPLICATION_FACTOR=3
  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.

Table 5. Event configuration properties
Property Default Description

apicurio.events.kafka.topic

registry-events

Name of the Kafka topic used for publishing registry change events. Applies to both SQL (via Debezium) and KafkaSQL storage variants.

apicurio.events.kafka.topic.replication.factor

Inherited from journal topic

Replication factor for the events topic (KafkaSQL only). If not set, inherits from the main KafkaSQL journal topic configuration.

apicurio.events.kafka.topic.cleanup.policy

delete

Cleanup policy for the events topic (KafkaSQL only).

apicurio.events.kafka.topic.retention.ms

-1 (infinite)

Retention time in milliseconds for the events topic (KafkaSQL only).

Storage variant support

Table 6. Event support by storage variant
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

 — 

 —