# Caching States

If no event carries the whole state, so that the state can not start from the latest event of one type (see **[Reading Long Streams](/docs/architecturekit/v2.0/reading-long-streams)**), the store can keep the states of the most recently used subjects in memory instead, so that the next command on one of them reads only the events written since.

To do so, hand over the `WithStateCache` option with the number of subjects to keep when creating the store:

```go
store := architecturekit.NewStore(client, "https://library.eventsourcingdb.io", architecturekit.WithStateCache(10_000))
```

Once the cache is full, the least recently used subject makes room. Such a subject is read in full again the next time, or from the latest event of the type given to `FromLatest`, if there is one (see **[Reading Long Streams](/docs/architecturekit/v2.0/reading-long-streams)**).

The cache only holds what was read, never what a command has written. Every command reads all events after the ones its state was built from, including those written by other processes, so the cache stays correct if several processes write to the same subjects.

The cache tells states apart by their type, not by the object. A state that is built anew for every command, for example by a function that returns it, is cached as well. This is why two different states that read the same subject need two different types: if one of them counts the loans of a book and the other one its returns, declare types such as `LoanCount` and `ReturnCount` rather than using `int` for both. If two states of the same type meet on the same subject, but differ in their initial value, in the event types they have `Evolve` rules for, ignore, or have upcasters for, or in `FromLatest`, `Execute` and `Load` return an error of the category `ErrPermanent` (see **[Handling Errors](/docs/architecturekit/v2.0/handling-errors)**).

*Note that the cache can not compare the `Evolve` functions themselves. Two states of the same type that are built alike, but compute something else, are not told apart.*

*Note that the very same state is not compared at all. The initial values of two different states of the same type are compared as `reflect.DeepEqual` compares them, except that every value equals itself: two functions in them are equal if both are `nil` or both are not, since functions can not be compared, and two floating-point numbers if they are equal or both `NaN`, as are the parts of two complex numbers. Only a map with a `NaN` key does not equal itself, since Go never finds such a key again.*

A cached state is handed to several commands, possibly at the same time. That is safe for a state that consists of values only, such as the `Book` state (see **[Defining State](/docs/architecturekit/v2.0/defining-state)**). A state that holds slices, maps, pointers, channels, functions, or interfaces, such as a field of type `error` or `any`, is only cached if it has a `Clone` function, which returns a copy that shares no data with the original. An interface counts as well, since it can hold any of the others. For example, a shelf that collects the IDs of the books that `BookShelved` events put on it needs one:

```go
type Shelf struct {
  BookIDs []string
}

var shelfState = architecturekit.NewState(Shelf{}).
  Evolve(func(shelf Shelf, event BookShelved) Shelf {
    shelf.BookIDs = append(shelf.BookIDs, event.BookID)
    return shelf
  }).
  Clone(func(shelf Shelf) Shelf {
    return Shelf{BookIDs: slices.Clone(shelf.BookIDs)}
  })
```

Without a `Clone` function, such a state is read as without a cache. The same function lets `Step` and `StepStored` leave a state unchanged (see **[Stepping Through States](/docs/architecturekit/v2.0/stepping-through-states)**), and copies the initial value at the start of every read, which an initial value with a map, a pointer or a channel that is not `nil`, or a slice with room for elements, requires (see **[Defining State](/docs/architecturekit/v2.0/defining-state)**).

*Note that as an initial value, `Shelf{}`, whose `BookIDs` are `nil`, does not require a `Clone` function, and neither does `Shelf{BookIDs: []string{}}`, since appending to a slice without room for elements allocates a new array. `Shelf{BookIDs: make([]string, 0, 10)}` does, since appending to it writes into the array that every copy shares.*

*Note that a `time.Time` counts as a value, since its location never changes.*

*Note that a number of `0` keeps no states, the same as leaving out the option, so that a configuration can turn the cache off. A negative number makes `WithStateCache` panic, and calling `Clone` twice, or with `nil`, panics as well.*
