alepha@docs:~/docs/reference/primitives$
cat $actor.md | pretty
2 min read

#$actor

#Import

typescript
1import { $actor } from "alepha/actor";

#Overview

Declare independent default and keyed actor state from an atom descriptor.

The atom supplies a stable name, schema and default, not live actor storage. Node and Bun default to per-container Memory; Redis requires explicit selection. Every identity carries alepha.name, so two apps on one backend never share state. Workerd uses a native Durable Object and fails if unbound. Browser and native client execution is unsupported.

Methods are pure synchronous reducers of readonly JSON state and arguments. Calls resolve to detached committed state. get(key) is synchronous; read() returns the default for a missing key without storing it. Actor snapshots never synchronize with alepha.store. Redis can rerun reducers on definite conflicts, so reducers must have no I/O, mutable captured dependencies, time/random reads or other side effects. Arguments are captured before the call waits. Reducer inputs are recursively frozen; callers may mutate returned snapshots without changing stored state. Omit optional values instead of passing undefined. Invalid, thrown or Promise transitions preserve state. Incompatible persisted data fails without resetting. A transport error can leave the commit outcome unknown; delivery is not exactly once. Changing the app name or atom name selects new state without migrating old data.

expiresAt derives an expiry from the state, never from the clock: a pure synchronous function returning an epoch-millisecond instant, or undefined for none. Once DateTimeProvider reaches it, the state reads as missing: the default, with the revision restarting. Expiring states are stored as protocol v2 envelopes; every other state keeps protocol v1 byte for byte.

#Examples

ts
 1import { $atom, Alepha, z } from "alepha"; 2import { $actor } from "alepha/actor"; 3  4const counter = $atom({ name: "counter", schema: z.integer(), default: 0 }); 5class Counters { 6  value = $actor({ 7    atom: counter, 8    methods: { add: (state, amount: number = 1) => state + amount }, 9  });10}11const counters = Alepha.create().inject(Counters);12await counters.value.add(); // default instance: 113await counters.value.get("alice").add(2); // keyed instance: 214await counters.value.read(); // default instance: 1