Event Type Versions
An event type is a contract between the systems that push events and the subscriptions that receive them. Sparrow treats it that way: every schema the type has ever had is kept as a numbered version, each pushed event records the version it was accepted under, and a type is never deleted.
You always refer to an event type by its name. The version is bookkeeping: push, subscriptions and the API resolve the name to the current version.
What creates a new version
Section titled “What creates a new version”Only a change to the schema creates a new version. Everything else changes the current version in place.
| Change | Result |
|---|---|
| The name does not exist yet | created: version 1 |
| A schema is added to a type that had none | updated: version 1 is filled in, and schema_defined_at records when |
| The schema changes (compared by value, so key order and whitespace never count) | new_version: the version number goes up and the previous version is kept |
| The schema is removed | new_version, and it is a breaking change |
Only the description, metadata or active changes | updated: same version |
| Nothing changes | unchanged: nothing is written |
PATCH /v1/event-types/{name} returns a change object saying which of these
happened, with version, previous_version and the list of changed fields.
Every write (register, PATCH, import, and auto-register on push) goes through the same rules, in a transaction that locks the event type’s row, so two concurrent changes can never claim the same version number.
Reading the history
Section titled “Reading the history”# Every version, newest firstcurl http://localhost:8080/v1/event-types/order.created/versions
# One version's schema and sample payloadcurl http://localhost:8080/v1/event-types/order.created/versions/2The event type’s own response carries version, and every pushed event
carries event_version: the version whose schema it was validated against.
A batch re-push keeps the original event’s version.
In the UI, the version in the event list links to the type’s history.
Breaking changes
Section titled “Breaking changes”Before a new version is written, Sparrow compares the old and new schemas from a subscriber’s point of view. The rule is strict: anything that could break a subscription’s payload transformation is breaking, and anything Sparrow cannot prove safe counts as breaking.
| Compatible | Breaking |
|---|---|
| Adding a property, optional or required | Removing a required property |
| Removing an optional property | Making a required property optional |
Narrowing a type (number to integer, or adding a type where there was none) | A type that admits a new kind of value (string to integer, integer to number, object to array) |
Changing value constraints: enum, minimum, maxLength, pattern, format, … | Removing the schema |
Any change under oneOf, anyOf, allOf, not, $ref, patternProperties, if/then/else or dependentSchemas |
Nested objects and array items are checked the same way, and every reason
names its path, for example customer.email: removed required property.
A breaking change to an event type that any subscription receives (by
name, or through a catch-all * subscription) is refused with 409 Conflict
and the reasons, and nothing is written. To apply it anyway, say so
explicitly:
curl -X PATCH 'http://localhost:8080/v1/event-types/order.created?allow_breaking=true' \ -H 'Content-Type: application/json' \ -d '{"event_schema": {"type": "object", "properties": {"id": {"type": "string"}}}}'In the UI, saving a breaking change asks you to type the event type’s name. If no subscription receives the type there is nothing to break, so no opt-in is needed; the change is still classified and reported.
When a schema change does reach a subscription whose template no longer fits,
the delivery fails visibly with error category template_error; see
Transforming Payloads.
Retiring an event type
Section titled “Retiring an event type”Event types are never deleted, and there is no delete endpoint. A definition with history cannot be removed at the database level either. To retire one, deactivate it:
curl -X PATCH http://localhost:8080/v1/event-types/order.legacy \ -H 'Content-Type: application/json' -d '{"active": false}'Pushes of an inactive type are rejected with 409. Its versions and past
events are kept, and setting active back to true reactivates it.
Unregistered event names
Section titled “Unregistered event names”By default, pushing an event whose type is not registered fails with 404:
production event types arrive by registering or importing
them. Because event types are never deleted, creating them implicitly would
turn every producer typo into a permanent name.
For local development, set SPARROW_AUTO_REGISTER_EVENTS=true (make run
does) to create a schema-less type on first push instead. The CLI’s
sparrow push registers an unknown type and retries on its own.
Reserved names
Section titled “Reserved names”Names starting with sparrow. (in any case) belong to Sparrow’s own system
events, such as sparrow.webhook.health_changed. You can subscribe to them,
but you cannot register, change, import, export or push them.