# Versioning Events

The database keeps the schema of an event type forever. If the shape of an event changes, introduce a new event type, and translate the stored events of the old type with an upcaster. If you change the schema of an existing event type instead, `register_schemas` fails on the next start (see **[Registering Event Schemas](/docs/architecturekit/rust/registering-event-schemas)**).

Suppose an earlier version of the library wrote events of the type `io.eventsourcingdb.library.book-lent`, with the fields `lentTo` and `until`. To translate them into `BookBorrowed` events, create a set of upcasters with `Upcasters::new`, which is made once, in a static. Then call its `upcast` function, and hand over the old event type and a function that receives the stored event as an `UpcastEvent` and returns the translated events. The data of an `UpcastEvent` is a `serde_json::Value`, so the application depends on `serde_json` for it, which you add with `cargo add serde_json`:

```rust
use std::sync::LazyLock;

use architecturekit::{Event, UpcastEvent, Upcasters};
use serde::Deserialize;

static LIBRARY_UPCASTERS: LazyLock<Upcasters> = LazyLock::new(|| {
  Upcasters::new().upcast("io.eventsourcingdb.library.book-lent", |event: UpcastEvent| {
    #[derive(Deserialize)]
    #[serde(rename_all = "camelCase")]
    struct BookLent {
      lent_to: String,
      until: String,
    }

    let old: BookLent = serde_json::from_value(event.data().clone())?;
    let data =
      serde_json::to_value(BookBorrowed { borrowed_by: old.lent_to, borrowed_until: old.until })?;

    Ok::<_, serde_json::Error>(vec![event.with_type(BookBorrowed::EVENT_TYPE).with_data(data)])
  })
});
```

The function may fail with any error that turns into a boxed error, here the one of `serde_json`. Upcasters may return more than one event, for example to split an event that recorded two facts into one event per fact. Derive each of them from the stored event with `with_type` and `with_data`, as above, so that they all keep its subject and its ID, which an event made with `UpcastEvent::new` would not. A projection then applies every one of them to a view, also if several of them change the same item (see **[Defining Views](/docs/architecturekit/rust/defining-views)**). If a returned event has an upcaster of its own, that one runs as well, so every version needs only a single step to the next one. The translated events are never written back.

A chain ends after 16 steps: if the event still has an upcaster then, reading fails with a permanent failure, which catches an upcaster that keeps its event type and would otherwise run forever. An error that an upcaster returns makes reading fail permanently as well.

To use the upcasters, return them from the `upcasters` function of the state. The upcasters then run before `evolve` sees the events:

```rust
impl State for Book {
  type Event = BookEvent;

  fn evolve(self, event: &BookEvent) -> Self {
    // ...
  }

  fn upcasters() -> Option<&'static Upcasters> {
    Some(&LIBRARY_UPCASTERS)
  }
}
```

Upcasting belongs to the event types, not to a single state, so make the set once and return the same one from every state, and from the `upcasters` function of every projection that reads these events (see **[Defining Projections](/docs/architecturekit/rust/projections#defining-projections)**). That way, the write side and the read side see the same events. A projection made with `projection_fn` brings along no upcasters, so one that reads older event types has a type of its own. To test the upcasters, see **[Testing Upcasters](/docs/architecturekit/rust/testing-deciders#testing-upcasters)**.

The kit decodes the data of an event with serde, which matches the names in the data exactly to the names of the fields, as `rename` and `rename_all` say, and ignores names that match no field. So data that names a field `BorrowedBy` does not fill the field that `BookBorrowed` writes as `borrowedBy`, and since that field is missing then, decoding fails, and so does reading. A field whose name changes, by case or by more, therefore needs an upcaster, as above. Only a field that is an `Option`, or one marked with `#[serde(default)]`, is left empty instead, which loses its value just the same.

*Note that calling `upcast` twice for the same event type panics while the set is built, rather than replacing the first upcaster.*
