Overview
Placement answers one question: which node runs an actor or grain. Actors are placed once, at spawn time. Grains are placed at activation time, every time they go from inactive to active. When cluster mode is disabled, all placement options are ignored and everything runs on the local node.- Actor: API:
Spawn. Placement decided: At spawn: the calling node, or an explicit node viaWithHostAndPort. Default strategy: Local. - Actor: API:
SpawnOn. Placement decided: At spawn: node selected by strategy and role. Default strategy:RoundRobin. - Singleton actor: API:
SpawnSingleton. Placement decided: At spawn: coordinator, or oldest node with the role. Default strategy: Leader. - Grain: API:
GrainOf/ first message. Placement decided: At activation: node selected by strategy and role. Default strategy:LocalActivation.
Actor placement
Local spawns
Spawn always creates the actor on the calling node. Cluster mode does not change that; it only writes the actor’s
record to the cluster registry synchronously, so a successful Spawn means the actor is immediately resolvable by name
via ActorOf and reachable from any node.
Local spawns
Spawning on an explicit node
WithHostAndPort targets a specific remote node by its remoting address. The spawn request is sent to that node and a
remote PID is returned.
Spawning on an explicit node
- Remoting must be enabled on the calling system; otherwise
SpawnreturnsErrRemotingDisabled. - The actor kind must be registered on the target node, through
ClusterConfig.WithKindsin cluster mode orActorSystem.Registerin remoting-only setups; otherwise the target rejects the request withErrTypeNotRegistered.
Strategy-based placement with SpawnOn
In cluster mode,SpawnOn selects a target node with a placement strategy and creates the actor there. The candidate
set is the current cluster membership, including the calling node. Outside cluster mode, SpawnOn behaves exactly like
Spawn.
- RoundRobin (default): Selection: Cycles through candidate nodes. Notes: Uses a cluster-wide shared counter, so the rotation is even across callers. Actors and grains keep separate counters.
- Random: Selection: Uniform random candidate. Notes: Stateless and cheap; distribution can be uneven over small samples.
- Local: Selection: Always the calling node. Notes: Use when locality matters (node-local caches, files, devices).
- LeastLoad: Selection: Candidate reporting the smallest load. Notes: Queries every candidate’s load metric over remoting before spawning; placement cost grows with cluster size.
- HashBased: Selection: The node that owns the registry partition of the actor’s name. Notes: Read from the local partition table with no network call. A name always maps to the same node from every caller, and the actor runs where its registry record is written. Load is not considered; see Partition Hashing.
Strategy-based placement with SpawnOn
pid.IsLocal() / pid.IsRemote() when the physical location matters.
An actor name identifies one actor across the cluster. Spawning a name that is already taken returns
ErrActorAlreadyExists. When several nodes spawn the same name at the same time, one spawn succeeds and the others
return ErrActorAlreadyExists and leave nothing behind. Stopping an actor never removes another actor’s registration.
Strategies see the topology at spawn time.
RoundRobin gives an even spread over a stable membership, but actors do
not move when nodes join later; redistribution only happens through relocation when a node
leaves. The same holds for HashBased: when a node joins, some partitions move to it, but the actors placed on their
previous owners stay where they are, so an actor and its registry record are co-located at spawn time only.What travels with a remote spawn
WhenSpawnOn or WithHostAndPort places an actor on another node, the spawn request carries the supervisor,
passivation strategy, serializable dependencies, stashing flag, reentrancy policy, and init timeout; they are restored
on the target node. The mailbox does not travel: a remotely placed actor uses the target system’s default mailbox, so
WithMailbox only takes effect for local placements.
Role-constrained placement
Nodes advertise roles throughClusterConfig.WithRoles. Roles let you dedicate node pools to workload classes (“api”,
“entity”, “projection”) and scale them independently.
Role-constrained placement
WithRole on the spawn side restricts the candidate set to nodes advertising that role. The placement strategy then
applies among the matching nodes only.
Role-constrained placement
- If no node in the cluster advertises the role,
SpawnOnfails with an error instead of falling back to an unsuitable node. - With
HashBased, the node that owns the actor’s partition must advertise the role. If it does not,SpawnOnfails with an error instead of placing the actor elsewhere, so a name always resolves to the same node. - Omit
WithRoleto allow placement on any node. - Without clustering, the role option is ignored and the actor spawns locally.
Singletons
Singleton placement is not strategy-based. A singleton runs on the cluster coordinator, or on the oldest node advertising the role given withWithSingletonRole. See Singletons.
Cross data center placement
WithDataCenter places the actor in another data center. The target is a random endpoint among the remoting addresses
that data center advertised at registration; the actor kind must be registered on the target data center’s systems.
Cross data center placement
Placement is not permanent
When a node leaves the cluster, its relocatable actors are recreated on surviving nodes; role constraints are honored during that redistribution. UseWithRelocationDisabled to pin an actor to the node it was placed on, accepting that it
is lost if that node goes down; its name is released so it can be spawned again. See Relocation.
Grain placement
Grains are virtual actors: you never spawn them explicitly, so placement happens when an identity is activated. The activation strategy and role are passed as options toGrainOf.
The current owner always wins
If the grain is already active anywhere in the cluster, every call routes to that node and the activation strategy is never consulted. Strategies only decide where an inactive grain comes to life. Ownership is claimed in the cluster registry with an atomic put-if-absent, so two nodes racing to activate the same identity converge on a single owner; the loser routes to the winner. See the activation guarantee.Activation strategies
- LocalActivation (default): Selection: The calling node. Notes: The grain lives where it is first used.
- RoundRobinActivation: Selection: Cycles through candidate nodes. Notes: Cluster-wide shared counter, independent from the actor counter.
- RandomActivation: Selection: Uniform random candidate. Notes: Stateless spreading.
- LeastLoadActivation: Selection: Candidate reporting the smallest load. Notes: Queries every candidate’s load metric over remoting; activation cost grows with cluster size.
Activation strategies
The defaults differ between the two models:
SpawnOn spreads actors with RoundRobin, while grains default to
LocalActivation. Unless you set a strategy, a grain activates on whichever node first touches its identity.Role-constrained activation
WithActivationRole restricts activation to nodes advertising the role, with the same semantics as actors: the strategy
applies among matching nodes, activation fails with an error when no node advertises the role, and the option is ignored
without clustering.
Role-constrained activation
Activation options are call-site properties
Grain options, including the activation strategy and role, take effect on the activation performed by theGrainOf call
that carries them. A grain that passivated and is later reactivated by a bare TellGrain or AskGrain on a stored
identity comes back with the default configuration. When placement must be enforced on every activation, resolve the
identity through GrainOf with your options before messaging.
Kind registration on host nodes
Remote activation, recreation, and relocation construct the grain as a zero value from its registered kind. Every node that can host the grain must know the kind:GrainOf auto-registers it on the calling node, and other nodes register it
at startup with RegisterGrainKind or ClusterConfig.WithGrains. Activation on a node that does not know the kind
fails.
Relocation
Grain placement after a node departure follows the virtual actor model:- Lazy relocation (default): the departed node’s grain directory entries are cleaned and each grain reactivates on a surviving node the next time it is addressed. The next activation runs the placement flow again.
WithGrainEagerRelocation: the grain is reactivated immediately on a surviving node when its host departs. Use it for grains that must stay warm, such as those driving timers or background work.WithGrainDisableRelocation: the grain is pinned to its host. If the node is lost, the in-memory instance is gone; addressing the identity again creates a fresh instance elsewhere, so persist state externally when it matters.
WithGrainEagerRelocation and WithGrainDisableRelocation are mutually exclusive; configuring both fails with
ErrGrainRelocationConflict. See Relocation for the full flow.
Choosing a strategy
- Keep
RoundRobinfor fleets of long-lived worker actors; it gives an even spread with negligible placement cost. - Use
Local/LocalActivationwhen the workload needs node-local resources or the caller should own it. - Use
LeastLoad/LeastLoadActivationfor heavyweight, long-lived workloads where one extra round of metric queries at placement time is cheap compared to running on a busy node. - Use
Randomwhen you want spreading without the shared counter round-trip and can tolerate short-term imbalance. - Use
HashBasedwhen a name should always land on the same node, and lookups from that node should find the actor’s registry record locally. PreferLeastLoadwhen load matters more than determinism. - Use roles to fence workload classes onto dedicated node pools; combine them with any non-local strategy.
See also
- Clustering: membership, configuration, and leadership
- Relocation: what happens to placed actors and grains when a node leaves
- Singletons: coordinator- and role-based singleton placement
- Multi Datacenter: cross data center topology
- Grains: grain lifecycle and activation guarantee
- Location Transparency: messaging after placement