Modes
A GoAkt actor system runs in one of two modes:- Standalone: What it gives you: Single-process actor system; all messaging is in-process. Setup:
NewActorSystem+Start, no extra options. - Clustered: What it gives you: Multi-node membership: location transparency, distribution, relocation, cluster
singletons. Setup:
WithRemote+WithCluster.
Standalone mode
In standalone mode, GoAkt runs in a single process. Actors are spawned under the user guardian and communicate through direct mailbox enqueue. No network or cluster setup is required. Use it for development and testing, single-node deployments, and services that do not need distribution. Limitations:- No remoting: actors cannot span multiple processes.
- No clustering: no discovery, no relocation, no cluster singletons, no grain distribution.
- Placement options on
SpawnOnandGrainOfare ignored; everything runs locally. - Single point of failure: a process crash stops everything.
Clustered mode
In clustered mode, multiple nodes form a cluster. Actors and grains are location-transparent: you send to a PID or a grain identity, and the framework routes to the correct node. Three components make that work:- Discovery: a pluggable provider (Consul, etcd, Kubernetes, NATS, mDNS, static) that tells the cluster how to find peers. See Service Discovery.
- Cluster registry: a distributed, partitioned key/value store (built on Olric) that records where every actor and grain lives. See Partition Hashing.
- Remoting: the TCP transport that carries messages between nodes. See Remoting.
Enabling cluster mode
Cluster mode has four hard requirements, all checked at start or by configuration validation:- Remoting: clustering needs remoting;
Startfails withclustering needs remoting to be enabledwhenWithRemoteis missing. - A discovery provider, set with
WithDiscovery. - A discovery port and a peers port, set with
WithDiscoveryPortandWithPeersPort. - At least one registered actor kind or grain kind, set with
WithKindsorWithGrains, so remote spawns, activations, and relocations can instantiate workloads on this node.
Enabling cluster mode
- Remoting port: Set with:
remote.NewConfig. Carries: Actor and grain messages between nodes. - Discovery port: Set with:
WithDiscoveryPort. Carries: Gossip and membership traffic. - Peers port: Set with:
WithPeersPort. Carries: Cluster registry replication.
TLS configured on the actor system with
actor.WithTLS applies to both remoting and the cluster transport. See
Remoting for certificate requirements.Configuration reference
NewClusterConfig returns a configuration with working defaults; only the four requirements above must be provided. The
options below are grouped by concern.
Workload and topology
- WithKinds: Registers actor kinds this node can host (remote spawn, relocation). Default: none.
- WithGrains: Registers grain kinds this node can host (remote activation, recreation, relocation). Default: none.
- WithRoles: Advertises node roles for role-constrained placement. Duplicates are removed; order is not meaningful. Default: none.
- WithGrainActivationBarrier: Delays grain activations until the minimum peers quorum is reached, or until
delapses.0waits indefinitely. Reduces churn during startup and rolling deployments. Default: disabled. - WithDataCenter: Enables the multi-DC control plane. See Multi Datacenter. Default: disabled.
- WithCRDT: Enables CRDT replication through a Replicator system actor. Without it there is zero CRDT overhead. See Distributed Data. Default: disabled.
Registry replication and storage
The cluster registry is partitioned across nodes and replicated per partition. These knobs control durability, consistency, and memory footprint.- WithPartitionCount: Number of registry partitions. Should be a prime number. See Partition Hashing. Default: 271.
- WithPartitionHasher: Hash mapping names and identities to partitions. Must be identical, deterministic, and stable on every node. Default: xxh3.
- WithReplicaCount: Copies kept of each partition. The default survives one node loss. Use 3 to tolerate two concurrent losses. Default: 2.
- WithWriteQuorum: Replicas that must acknowledge a registry write. Must be
>= 1and<= replicaCount. Default: 1. - WithReadQuorum: Replicas consulted per registry read. Must be
>= 1and<= replicaCount. Default: 1. - WithMinimumPeersQuorum: Members a node must see in its own membership view before the registry serves it: at
startup, when the registry map is created, before every registry request received from another node, and before the
leader recomputes the routing table. Also the quorum the grain activation barrier waits for. GoAkt has no split-brain
resolver, so this setting is the only partition safeguard. With the default of 1, each side of a network split keeps
serving, takes its own oldest member as leader, sees the other side’s nodes as departed and relocates their actors, so
an actor or a singleton can run on both sides until the split heals. A value above half the cluster size keeps the
minority side from recomputing its routing table and from serving registry requests to its peers, so it cannot
relocate; it does not stop the minority’s already-running actors. Keep it
<= replicaCount. Default: 1. - WithTableSize: In-memory size of the registry key/value store on this node. Default: 4 MB.
- WithStoreDir: Directory for the node’s cluster store, the BoltDB file that holds peer state while the node runs.
The file is created on start and deleted on stop, so an ephemeral writable volume (for example an
emptyDir) is enough. Set it when the home directory is not writable, such as a pod with a read-only root filesystem or a sandbox without$HOME. Default:~/.goakt/cluster.
readQuorum + writeQuorum > replicaCount) is not enforced, and the default
(replicaCount=2 with both quorums at 1) deliberately does not follow it: the registry is rebuildable, single
activation is arbitrated by the partition’s primary owner rather than by quorum overlap, and quorums of 1 keep registry
writes succeeding while a node is down. For a majority configuration, use replicaCount=3 with writeQuorum=2 and
readQuorum=2, accepting higher write latency and fan-out.
Timing
- WithWriteTimeout: Maximum duration of a registry write before it fails. Default: 1s.
- WithReadTimeout: Maximum duration of a registry read before it fails. Default: 1s.
- WithBootstrapTimeout: Maximum wait for cluster formation during
Start; the system fails to start when it elapses. Default: 10s. - WithShutdownTimeout: Maximum duration of a graceful cluster shutdown. Default: 3m.
- WithClusterStateSyncInterval: How often nodes synchronize routing tables. Keep it greater than the write timeout. Default: 1m.
- WithClusterBalancerInterval: How often the balancer evaluates placement and acknowledges rebalance epochs. Keep it shorter than the state sync interval so epochs do not stack. Default: 1s.
- WithNetworkProfile: Describes the network the cluster nodes share and tunes failure detection for it.
NetworkProfileLAN(default) is for nodes in one data center or availability zone.NetworkProfileLocalis for nodes on one host or a low-latency test cluster; it confirms failures fastest and is the most likely to mistake a long pause for a crash.NetworkProfileWANis for nodes spread across regions or reached over the public internet; it tolerates latency and loss and confirms failures slowly. - WithConvergenceTimeout: Bounds how long the cluster waits, after it confirmed that a node joined or left, for
every node to route on the same membership before it publishes
NodeJoinedorNodeLeftanyway. Default: 10s. This is not the failure confirmation time, which the network profile sets and which ends before this wait starts; it bounds the convergence that follows, normally under a second and up to a few seconds when the departed node was the oldest member. A shorter bound does not make failures visible sooner and can publish the event while a node still routes to the departed one; to detect failures sooner, pick a faster network profile.
Failure detection
When a node stops abruptly, the survivors confirm its loss after several missed probes, then converge on the new membership, then publishNodeLeft and relocate its actors. Confirmation time depends on the network profile and grows
slowly with the cluster size; convergence normally takes under a second; relocation starts about three seconds later,
once the cluster store has settled. Expected time from the crash to NodeLeft:
Faster confirmation means a higher chance that a garbage collection pause or CPU throttling is mistaken for a crash,
which relocates a healthy node’s actors for nothing. Keep the default unless the deployment matches another profile.
With TLS enabled, the Local and LAN rows are about 11s, 15s and 19s.
Registry consistency
Actor and grain creation is synchronous with respect to the cluster registry:Spawn, SpawnOn, SpawnSingleton, and
grain activation only return once the registry record is written to the cluster store. As soon as a creation call
succeeds, the actor is resolvable by name, or by qualified name (parent/child, built with actor.QualifiedName) for
a child, for example via ActorOf, and reachable from any node in the cluster, with no propagation window to retry
around. When the registry write fails, the creation call returns the error and the actor or grain is stopped, so a
failed creation leaves nothing behind.
Placement
Where a new actor or grain lands is controlled at spawn or activation time through placement strategies (round robin, random, local, least load) and node roles. See Placement for the strategies, role constraints, and defaults for both actors and grains.Relocation
When a node leaves, the leader relocates its actors and grains to remaining nodes. Singleton actors move to the leader; others are distributed. Actors can opt out of relocation via spawn options. See Relocation for the full flow, configuration, and relocatability requirements.Leadership
Exactly one node in the cluster acts as the coordinator (leader) at any given time. The leader drives internal responsibilities such as relocation and cluster singleton placement, but its status is also queryable from application code:- ActorSystem.IsLeader: Reports whether the local node is the current cluster coordinator.
- ActorSystem.Leader: Returns the
*remote.Peerdescribing the current cluster leader.
ErrClusterDisabled when clustering is not enabled.
Leadership
LeaderChanged event on its local
event stream, alongside NodeJoined and NodeLeft, carrying the new leader’s address. Like
the other topology events, it exists for observability (monitoring, logging, dashboards); leadership itself is managed
entirely by the framework.
Leadership
LeaderChanged is eventually consistent. It is derived from cluster topology events, so it is published once per
leadership change shortly after the cluster settles, and the node’s initial leadership is seeded silently rather than
announced. Delivery is best-effort and may be missed under heavy event churn. Treat it as a notification, not a source
of truth. When you need the authoritative current leader, call IsLeader(ctx) or Leader(ctx).See also
- Placement: where actors and grains run
- Service Discovery: discovery provider options
- Partition Hashing: how names map to registry partitions
- Multi Datacenter: spanning clusters across data centers
- Relocation: node departure and workload redistribution
- Remoting: transport configuration and TLS