Proto Actor for Go — a distributed actor framework built on gRPC and Protobuf
What this repository is
asynkron/protoactor-go is the Go half of Proto Actor, an actor-model framework that also has a C# implementation in protoactor-dotnet. The two speak the same wire protocol, so actors written in either language can exchange messages. The README describes it as cross-platform actor support between Go and C#, built on existing technology rather than new infrastructure.
The project's stated design principles are worth reading before you adopt it: a minimal API without "enterprisey JVM like containers and configurations", reusing proven pieces (gRPC streams for transport, Consul.IO for clustering), Protobuf serialization as an explicit concern rather than something hidden, and speed over magic. The README reports the remoting layer passing roughly 2.7 million messages per second between nodes using only two actors in a log while preserving order — six times what it attributes to Akka's Artery transport.
The Go implementation is still marked beta; the API may change before 1.0, though the README notes production users already exist. The latest release tag is 0.4.0, and the module targets Go 1.25.3 under Apache-2.0.
The core: actors, Props, PIDs
The actor package defines the runtime's vocabulary. An ActorSystem hosts actors; the README examples use its Root context. You create one with actor.NewActorSystem(); its Root context is your entry point.
Actors are described by Props; the README shows producer functions via PropsFromProducer and supervision options via WithSupervisor. The actor package also includes mailboxes/dispatchers and middleware. A PID (*PID) is the addressable handle — a process ID plus an address — through which you send messages.
The minimal example from the README shows the shape:
type Hello struct{ Who string }
type HelloActor struct{}
func (state *HelloActor) Receive(context actor.Context) {
switch msg := context.Message().(type) {
case Hello:
fmt.Printf("Hello %v\n", msg.Who)
}
}
context := actor.EmptyRootContext
props := actor.PropsFromProducer(func() actor.Actor { return &HelloActor{} })
pid, err := context.Spawn(props)
How an actor starts
The core operations shown in the README for talking to actors are Send and Stop, both called on the root context, plus spawning through Spawn, which returns a PID; the returned sources also show a Root.PoisonFuture. The README shows that a spawned actor receives the Started system message.
Two details matter. First, lifecycle events are messages, not method overrides — your actor's Receive switches on *actor.Started, Stopping, Stopped, and Restarting. Second, supervision is explicit: root actors fall under a default strategy that always issues a restart directive, while parents supervise children. You customize with strategies like actor.NewOneForOneStrategy(maxRetries, withinDuration, decider), where the decider returns a Directive such as RestartDirective or StopDirective.
Remoting and clustering
The remote/ package is a thin wrapper over gRPC. A node binds with remote.Start("localhost:8090"), as shown in the README, and registers named actor kinds so they can be spawned remotely via remote.Register(name, props). Messages carry PIDs that include the target address; endpoint components such as EndpointWriter connect over gRPC streams between nodes. Message contracts are defined in .proto files that import actor.proto so messages can embed PID fields.
The cluster/ package layers membership and virtual actors on top of remoting. A cluster uses gossip for topology, tracks members through a member list, and supports "grains" — virtual actors addressed by identity rather than location, activated on whichever node owns them. The README's cross-platform story is strongest here: because serialization is Protobuf and transport is gRPC, a .NET actor can communicate with a Go actor.
The returned sources show an etcd membership provider under cluster/clusterproviders/; go.mod includes dependencies for Consul, etcd, and ZooKeeper. The cluster also ships PubSub. Identity lookup is a pluggable interface; the disthash package under cluster/identitylookup/disthash provides one implementation built on a partition manager.
Persistence, routing, testing
The persistence/ package adds event sourcing through a Provider abstraction with a Couchbase-backed implementation under persistence/protocb. The Makefile excludes persistence from the default test run. The persistence package provides event and snapshot stores with Replay/OfferSnapshot messages; the example under examples/persistence/ shows a provider persisting events and snapshots through those interfaces.
The router/ package provides routing strategies for pools and groups of routees, including a broadcast router that fans out to all routees and a consistent-hash router. The testkit/ package is the testing companion for driving actors from tests; it provides a TestProbe and test mailbox statistics alongside the actor runtime's own event stream.
Observability is built in through OpenTelemetry metrics (Prometheus exporter) wired into both actor and cluster layers, plus an event stream for pub/sub within a system. There are also plugin/, stream/ and scheduler/ packages rounding out the feature set.
Building and testing
The repository uses Go modules; examples live under examples/. The Makefile drives everything: make build compiles, proto regenerates Protobuf definitions via buildall.sh, and test targets exclude examples/, persistence/, and scheduler/:
go test $(PACKAGES) -timeout=30s
There are variants for short tests (-short), race detection, linting with revive, vetting, and benchmarks. The README's build instructions predate modules in places (it mentions $GOPATH and make to generate protobuf definitions), but the modern path is plain Go module usage.
Who it is for
Proto Actor suits teams that want actor-model concurrency — decoupled, distributed-by-default, fault-tolerant — without writing their own transport or serialization. The cross-platform angle matters if you're migrating from .NET to Go and need both runtimes talking during the transition: "reinvent by not reinventing," as the README puts it.
The trade-off is that this is beta software with a changing API, and some features (cluster providers, persistence backends) pull in external infrastructure. If you want actors purely within one process, the core actor package alone gives you that; if you need multi-node placement and virtual actors, you're committing to gRPC remoting plus a membership store.
asynkron/protoactor-go: 2 MB in 670 files, indexed Nov 9, 2026 after 0.00 hours of indexing. License: Apache-2.0. Source: https://github.com/asynkron/protoactor-go.
Ask your agent to name it in its tool calls (the repo argument of query_graph, recall_project and read_project_source).
Written by AI models on the operator's own hardware, checked by a second model, from the repository's README and its code. Back to the shelf