Skip to main content
The ActorSystem is the top-level runtime that hosts actors and orchestrates messaging, clustering, remoting, and lifecycle. Run one ActorSystem per process; this is not enforced, and several systems can run in one process as long as their remoting and cluster ports differ. All actors, grains, and system services run within it.

Role and responsibilities

  • Actor hosting: Spawns and supervises actors under the /user guardian. Manages the actor tree and parent-child relationships.
  • Messaging: Routes messages locally or remotely. Serializes and deserializes when crossing node boundaries.
  • Clustering: When enabled, joins a cluster, discovers peers, and provides location-transparent actor resolution.
  • Remoting: When enabled, exposes a TCP server and client for cross-node communication.
  • Event stream: Publishes system and cluster events (ActorStarted, NodeJoined, Deadletter, etc.) to subscribers. See Event Streams.
  • PubSub: When WithPubSub or cluster is enabled, a topic actor manages application-level topics. See PubSub.
  • Scheduling: Delivers one-time, recurring, and cron-scheduled messages to actors.
  • Coordinated shutdown: Runs shutdown hooks, stops actors depth-first, and leaves the cluster gracefully.
See Architecture Overview for the component diagram.

Lifecycle

Lifecycle
  • NewActorSystem: Applies options; does not start services.
  • Start: Initializes remoting (if enabled), cluster (if enabled), scheduler, eviction, passivation, and system actors. Handle SIGTERM/SIGINT and call Stop for clean shutdown.
  • Stop: Runs coordinated shutdown hooks, stops user actors, deactivates grains, shuts down system actors, leaves cluster, stops remoting. Does not exit the process; call os.Exit if needed.
Details: Coordinated Shutdown, Quickstart.

API surface

Spawning

  • Spawn: Create a named actor locally (or on a specific host with WithHostAndPort).
  • SpawnOn: Create actor on a cluster node (see Placement) or in another data center (WithDataCenter).
  • SpawnFromFunc: Functional actor; no Actor implementation.
  • SpawnNamedFromFunc: Named functional actor.
  • SpawnRouter: Router with a pool of routees. Not cluster-relocatable.
  • SpawnSingleton: Cluster singleton; one instance per name across the cluster, hosted on the oldest node. See Singletons.
In cluster mode an actor name identifies one actor across the cluster. Spawning a name that is already taken returns ErrActorAlreadyExists, and when several nodes spawn the same name at the same time, one spawn succeeds. A child’s name is unique within its parent. See Placement. See Actor Lifecycle, Routers, Singletons, Clustering.

Resolution and inspection

  • ActorOf: Resolve a PID by name. Local or remote; use pid.IsLocal / pid.IsRemote when it matters.
  • ActorExists: Check if an actor exists locally or in the cluster.
  • Actors: Enumerate all actors visible to this node. Use sparingly; cluster scan is costly.
  • NumActors: Count of local actors only.
  • Partition: Partition ID for a given actor name (cluster hashing).
  • InCluster: Whether the system is running in cluster mode.
See PID, Location Transparency.

Messaging from outside

From outside the actor system (e.g. main), use system.NoSender():
  • NoSender().Tell(pid, msg): Fire-and-forget.
  • NoSender().Ask(ctx, pid, msg, timeout): Request-response; actor must call ctx.Response(resp).
For processes that do not run an actor system (CLI, API server, batch job), use the Client package to connect to the cluster and send messages by actor name. See Messaging.

Scheduling

  • ScheduleOnce: One-time delivery after delay.
  • Schedule: Recurring delivery at interval.
  • ScheduleWithCron: Cron-based delivery.
  • CancelSchedule: Cancel by reference.
  • PauseSchedule / ResumeSchedule: Pause or resume a scheduled task.
Use WithReference(id) when scheduling if you need to cancel, pause, or resume. See Scheduling.

Events and observability

  • Subscribe: Create an event-stream subscriber for system/cluster events. Returns eventstream.Subscriber; iterate via Iterator.
  • Unsubscribe: Release subscriber; call to avoid leaks.
  • TopicActor: Topic actor PID for PubSub (when WithPubSub or cluster is enabled). Send Subscribe, Unsubscribe, Publish.
  • Metric: Node-level metrics (actor count, mailbox sizes, throughput, uptime).
See Event Streams, PubSub, Observability.

Cluster and lifecycle control

  • Kill: Stop an actor by name (local or remote).
  • ReSpawn: Restart an actor with its whole subtree. The same actor values are reused and only PreStart runs again, so state that PreStart does not reset survives the restart.
  • Name: Actor system name.

Dependency injection

  • Inject: Register dependency types with the actor system after startup. Enables restoration during cluster topology changes and when creating actors on remote hosts. Must be called after Start.

Configuration options

Options are passed to NewActorSystem(name, opts...). Each option is documented in the source; they are grouped here by concern.
  • Core
    • WithLogger: Custom logger. WithLoggingDisabled for no-op.
    • WithActorInitTimeout: Actor startup timeout.
    • WithActorInitMaxRetries: Retries for actor init.
    • WithShutdownTimeout: Total shutdown timeout (default: 3 min).
    • WithAskTimeout: System-wide timeout for internal Ask round-trips (default: 5s).
    • WithDefaultSupervisor: Fallback supervisor for actors without explicit config.
  • Remoting & cluster
    • WithRemote: Enable remoting. See Remoting.
    • WithCluster: Enable clustering. See Clustering.
    • WithTLS: Deprecated: use remote.WithTLS on the remote config. See TLS.
    • WithoutRelocation: Disable actor relocation on node departure.
  • Extensions & capabilities
  • Shutdown & eviction
    • WithCoordinatedShutdown: Shutdown hooks. See Coordinated Shutdown.
    • WithEvictionStrategy: Passivation when actor count exceeds limit.
  • Advanced
    • WithThroughputBudget: Messages an actor may process per scheduler turn (default: 32). See Throughput budget for tuning profiles.
    • WithDispatcherPoolSize: Size of the worker pool that runs actor and grain turns (default: max(GOMAXPROCS, 2)), for handlers that block in their turn. See Worker pool size for the trade-off.
    • WithPartitionHasher: Deprecated: use ClusterConfig.WithPartitionHasher. See Partition Hashing.

Tuning the dispatcher

Actors and grains do not own goroutines. Each ActorSystem runs them on one fixed pool of worker goroutines, the dispatcher. A worker takes an actor that has messages, handles up to a budget of them in one turn, and then moves on so other actors get a turn. runtime.NumGoroutine() therefore stays near the worker count however many actors are active. Two options tune the dispatcher. Neither changes the guarantees your code relies on: an actor or grain still handles one message at a time, and messages from one sender to one actor still arrive in the order they were sent.

Throughput budget

WithThroughputBudget sets how many messages a worker handles from one actor before it yields to the next. The default of 32 favors fairness and predictable tail latency. A larger budget spreads the cost of scheduling over more messages and keeps a busy actor’s state in the CPU caches, which raises aggregate throughput. The cost is fairness: a busy actor holds its worker longer before its peers get a turn.
Tuning the throughput budget
  • 8 to 16: latency-critical systems with many small actors, such as control planes and request routing.
  • 32 (default): a balanced setting for most mixed workloads.
  • 64: a safe upgrade for throughput-oriented systems, typically 5 to 15% more aggregate throughput on message-heavy workloads.
  • 128: ingest and aggregation, such as log pipelines, event firehoses and batch processors.
  • 256 and above: synthetic benchmarks or a single hot actor only. Throughput flattens and tail latency grows.
Values of zero or less keep the default. A yield is a pause, not a reorder: the messages left in the mailbox are handled in order on the actor’s next turn.

Worker pool size

The pool defaults to max(GOMAXPROCS, 2) workers, one per OS thread, which is right for handlers that compute and return. A handler that blocks in its turn, on a database call or a synchronous request, holds its worker for the whole wait. With the default pool, no more than GOMAXPROCS actors and grains make progress at once, whatever their number: on a two-CPU container, two. WithDispatcherPoolSize sets the pool size for the system:
Sizing the worker pool
Values of zero or less keep the default, and a value of one is raised to two. With a single worker, a handler that waits on another actor inside its turn would hold the only worker that could answer it. Size the pool like a connection pool: the number of workers is about the throughput you need times the latency of the blocking call.
A larger pool is not free. Every actor and grain shares it, and producers scan the pool for a parked worker on each wake, so a pool much larger than GOMAXPROCS slows dispatch for handlers that do not block. Raise the pool only when handlers wait in their turn, and prefer PipeTo where the wait can leave the turn.
The table shows the benchmark suite with the default pool and with WithDispatcherPoolSize(256), on an 8-CPU Apple M1 with GOMAXPROCS=8, five runs each. These handlers do not block, so the numbers are the pure dispatch cost of the larger pool. Per-actor and per-grain heap did not change. Request/reply pays the most because every round trip wakes a parked worker, and with a large pool that is usually a cold one. Plain tells to a busy actor are unaffected: the worker never parks. The gain on the other side is what the option exists for. With 200 grains that each wait 10 ms in their turn, five messages each and all 1000 asks in flight, a node with GOMAXPROCS=2 takes 5.5 s with the default pool and 53 ms with 256 workers, because the 200 grains wait at the same time instead of two at a time. How the dispatcher is built (its ready queue, work stealing and the state machine that keeps one actor on one worker) is covered in chapter 7 of the maintainers’ book.

Component relationships

The ActorSystem composes:
  • Remoting: TCP server/client; used when WithRemote is set.
  • Cluster: Membership, discovery, Olric DMap; used when WithCluster is set.
  • Event stream: In-process pub/sub; always present; topic actors when WithPubSub is set.
  • Scheduler: For ScheduleOnce, Schedule, ScheduleWithCron.
  • Extensions: Accessed via ctx.Extension(id) from actors.
Actors obtain the system via ctx.ActorSystem() (or ReceiveContext, GrainContext). Use it to spawn children, resolve actors, schedule, or access extensions. Do not store the ActorSystem in actor state; always obtain it from context.

Further reading