idleAfterMs (default 20 minutes) is how long an activation survives without a call. The
sweeper runs every sweepIntervalMs (default 60s); set either to 0 to disable.
Two things count as activity that people expect not to:
An open live watch keeps the actor alive, deliberately — so idle
collection cannot deactivate an actor out from under a subscriber.
A running task holds a keep-alive until it finishes.
A ctx.timer tick does not keep the actor alive, and that is intentional: a volatile
timer is a convenience, not a reason to pin an object in memory. If you need the actor to wake
up later regardless, use a durable reminder.
A soft LRU cap, enforced by the sweeper, with deactivation reason capacity. Soft is the
operative word:
Busy actors and actors holding a keep-alive are never shed.
The live count may therefore exceed the cap.
State survives — a shed actor reactivates from storage on its next call.
It is a memory guardrail, not an admission-control mechanism. Watch byReason.capacity in
metrics: a cap that is shedding constantly is either too low or
hiding a key-cardinality problem.
Returns { type, key, queued, ageMs, idleMs, keptAlive, tasks } per activation. sortBy
accepts 'queued', 'age' or 'idle', and type filters to one actor type.
queued is the one to look at first: a persistently non-zero queue depth is a hotspot, and
the fix is usually to shard the key or move I/O out of the turn — see
Metrics for the queueMs versus turnMs distinction.
Actor keys can be personal data. host.activations() returns them, which is why the ops
endpoint keeps the activation list off by default and requires a secret.
Stops accepting new calls, drains in-flight turns, flushes pending write-behind saves, runs
onDeactivate for every activation and then the app's onStop hooks in reverse order.
On Node, wire it to signals with attachSignalHandlers — see
Running a host on Node. In a cluster, a graceful stop announces leaving
before handing off, which is why liveness and readiness
are allowed to disagree.