Skip to main content

Registering and evolving schemas

Register a schema for an event type and the server rejects non-conforming payloads at write time, before they reach the log. See Schema validation.

Register

await pool.RegisterSchemaAsync(new RegisterSchemaRequest
{
ClientId = adminClientId,
SchemaKey = new SchemaKey(orgId, ordersType, eventTypeMajor: 1, eventTypeMinor: 0),
SchemaType = SchemaType.Json, // Json, Avro, or Protobuf
Schema = """
{
"type": "object",
"required": ["sku", "qty"],
"properties": {
"sku": { "type": "string" },
"qty": { "type": "integer", "minimum": 1 }
}
}
""",
});

A schema is keyed to (org, aggregate type, major, minor) and applies to exactly that key. From then on, a write of that event type whose payload does not conform is rejected with SchemaValidationException (2022), and nothing in the request is appended.

What Schema holds depends on the type:

SchemaTypeSchema stringPayload checked as
Jsona JSON Schema documentUTF-8 JSON, validated against the schema
Avroan Avro schema (JSON)an Avro binary datum decoded with that schema
Protobufbase64(FileDescriptorSet):MessageNamethat message, decoded from the payload bytes

The schema string is capped by --max-schema-size-bytes (default 16384). Format details are in Schema formats.

What validation does not cover

  • Unregistered types. An event type with no schema at its exact (major, minor) is not validated at all. Bump the minor and forget to register, and that version goes in unchecked.
  • Encrypted events. The server skips validation for any event that carries an Iv. It cannot read ciphertext, so it does not try. See Encryption.
  • Events already written. A schema applies to writes after it registers. The log is not re-checked.

Evolve

Register a new schema for the new version rather than mutating the old one. There is no update or delete:

  • a minor bump for a backward-compatible change (a new optional field),
  • a major bump for a breaking one.

Both versions stay registered and valid, so producers and consumers migrate on their own schedule.

Errors

All come back as SchemaErrorException except 2022, which is its subclass SchemaValidationException.

CodeNameCause
2020RegisterSchemaAlreadyExistsThat (org, type, major, minor) is already registered.
2021RegisterSchemaInvalidThe schema does not parse or compile, or exceeds --max-schema-size-bytes.
2022WriteSchemaValidationFailedA write's payload does not conform.
2024RegisterSchemaUnsupportedTypeUnknown SchemaType.
2029RegisterSchemaCoordinationFailedNot every shard confirmed the registration.

Registration runs on the leader. It lands on shard 0 first, then fans out to the other shards.

A 2029 does not retry cleanly

A 2029 means shard 0 has the schema and at least one other shard does not. Retrying the same registration fails fast with 2020 at shard 0 and never reaches the shards that missed it, so writes routed there go unvalidated. Treat a 2029 as an incident, not a retry.