API reference › @evolu/common › local‑first/Schema › Mutation

type Mutation<S, Kind> = <TableName>(
  table: TableName,
  values: MutationValues<S[TableName], Kind>,
  options?: MutationOptions,
) => {
  id: StandardSchemaV1.InferOutput<S[TableName]["id"]>;
};

Defined in: packages/common/src/local-first/Schema.ts:502

Mutation function type. Accepts already-validated values — validation is the caller's responsibility using any Standard Schema library (Evolu Type, Zod, Valibot, ArkType, etc.).

Evolu does not use SQL for mutations to ensure data can be deterministically merged without conflicts. Explicit mutations also allow Evolu to automatically update SystemColumns and encourage developers to consider the number of changes produced, unlike SQL where a single query can inadvertently generate a large volume of CRDT messages. Each mutation produces exactly one CrdtMessage containing all provided columns.

Each mutation must fit within maxMutationSize. Give every column a Type with a maximum length, such as NonEmptyTrimmedString1000 or maxLength(100_000)(Uint8Array), so that a table's largest values add up to less than the limit and input that is too large is rejected where it enters the app. A larger mutation throws before anything is saved, so the code after it does not run. Check unbounded input with Evolu.getMutationSize. Large binary data, such as images or videos, does not belong in a single mutation; a chunked API for it is planned.

Binary values are copied when the mutation is made, so later changes to a Uint8Array do not change what is saved.

  • insert: all non-nullable columns required, nullable columns optional, id omitted (auto-generated)
  • update: only id required, everything else optional
  • upsert: like insert but id required too