Skip to content

Mutations

Mutations live in <entity>.mutations.ts and contain the raw write operations that execute against PowerSync.

  • plain transaction-based write functions
  • no React hooks
  • no query lookups
  • no confirmation logic
  • as little policy as possible

These files should stay low-level and predictable.

Mutation hooks (use-<entity>-mutations.ts) wrap raw mutations with:

  • React hook interface
  • hard invariant enforcement before writing
  • authoritative write boundary behavior

If an operation can be blocked by business rules, the mutation path must enforce those rules independently of the action layer.

Mutation hooks derive the required current-state facts themselves before writing. This is the strongest safety boundary.

Mutation hooks require an operation input object and enforce the guard using that input. The input should not be optional when the write is safety-sensitive.

Optional guard input that silently disables enforcement. That weakens the architecture because callers can bypass the rule by omission.

If a raw mutation file starts growing UI-aware or policy-heavy branching, that logic probably belongs in:

  • guards
  • workflows
  • action hooks
  • or mutation-hook enforcement

not in the raw mutation file itself