# Schemas and Evolution — Event-Driven Architecture & CQRS

Source: https://www.skillbyai.com/en/event-driven-architecture/e-schema

> Evolve event schemas without breaking existing consumers.

## Events are a public API

Once other teams consume an event, its shape is a **contract**, often longer-lived than a REST API because old events may be replayed years later. Describe events with a schema (**JSON Schema**, **Avro** or **Protocol Buffers**) and store schemas in a **schema registry** that checks compatibility when a producer registers a new version. Compatibility modes: **backward compatible** (new consumers can read old events, so you may delete fields or add optional fields with defaults), **forward compatible** (old consumers can read new events, so you may add fields they ignore), and **full** (both). Safe changes: adding an optional field, adding a new event type. Breaking changes: renaming or removing a required field, changing a type, changing meaning. For a breaking change, publish a **new version** (`OrderPlaced.v2`) alongside the old one, migrate consumers, then retire the old version.

## An additive, compatible change in Avro

The new field has a default, so old and new readers both cope.

```json
{
  "type": "record",
  "name": "OrderPlaced",
  "namespace": "com.shop.orders",
  "fields": [
    { "name": "orderId",    "type": "string" },
    { "name": "customerId", "type": "string" },
    { "name": "totalMinor", "type": "long" },
    { "name": "currency",   "type": "string" },
    { "name": "channel",    "type": "string", "default": "web" }
  ]
}
```

## Adding a column to a printed form

Adding an optional box at the bottom of a form is fine; old clerks ignore it. Renaming the "Amount" box to "Total" means every clerk in every branch must be retrained at once.

**Quiz:** Which change is usually safe for existing consumers?

- [ ] Renaming orderId to id
- [x] Adding an optional field with a default value
- [ ] Changing totalMinor from long to string
- [ ] Removing the currency field

*Answer:* Adding an optional field with a default value. Adding optional fields with defaults is compatible; renames, type changes and removals break readers.
