Skip to main content
eGo is a companion framework built on top of GoAkt that adds event sourcing, durable state, CQRS projections, and saga orchestration. It uses Protocol Buffers for commands, events, and state, and relies on GoAkt for actor execution, supervision, clustering, and remoting. eGo is not bundled with GoAkt

Installation

go get github.com/tochemey/ego/v4

Why eGo

GoAkt provides the actor runtime β€” messaging, supervision, clustering, streams. eGo builds on that runtime to solve the persistence and workflow layer:
ConcernGoAkteGo
Actor executionYesUses GoAkt
Clustering and remotingYesUses GoAkt
Event sourcingβ€”EventSourcedBehavior
Durable stateβ€”DurableStateBehavior
CQRS projectionsβ€”Projection runner
Saga / process managerβ€”Saga
Event publishingβ€”Kafka, Pulsar, NATS, WebSocket
Snapshot recoveryβ€”SnapshotStore
Encryption at restβ€”Events and snapshots

Core behaviors

eGo offers two persistence models. Choose based on whether you need a full event history or just the latest state.

Event-sourced behavior

EventSourcedBehavior captures state changes as domain events. Commands are processed sequentially β€” each command produces zero or more events that are persisted to a journal. State is rebuilt by replaying events on recovery.
MethodPurpose
ID()Unique behavior identifier
InitialState()Returns the zero-value state (protobuf message)
HandleCommand(ctx, command, priorState)Validates the command against current state and returns resulting events
HandleEvent(ctx, event, priorState)Applies a single event to produce the next state
Additional capabilities:
FeatureDescription
SnapshotsPeriodic state snapshots to reduce replay time on recovery
Event batchingAccumulate events across commands and flush in a single store write
Retention policiesAutomatically clean up old events and snapshots after a successful snapshot
Event adaptersTransform persisted events during replay for schema evolution
EncryptionAt-rest encryption of events and snapshots

Durable-state behavior

DurableStateBehavior persists only the latest state β€” no event log, no replay. Each successful command produces a new state version, and only the latest version is stored.
MethodPurpose
ID()Unique behavior identifier
InitialState()Returns the zero-value state (protobuf message)
HandleCommand(ctx, command, priorState, revision)Validates the command and returns the new state
This model is a good fit for configuration-style entities, lower-overhead persistence needs, and use cases where audit replay is not required.

Choosing a model

AspectEvent-sourcedDurable-state
PersistenceDomain eventsLatest state
RecoveryReplay (optionally from snapshot)Load latest version
HistoryFull audit trailNone
ComplexityHigherLower
Best fitBusiness-critical workflowsConfiguration, simple CRUD

Persistence stores

eGo uses pluggable store interfaces. In-memory stores ship for testing; production backends are in the ego-contrib repository.
StoreInterfaceBackends
Event journalpersistence.EventsStorePostgres, MongoDB
Snapshotspersistence.SnapshotStorePostgres, MongoDB
Durable statepersistence.StateStorePostgres, MongoDB
Projection offsetsoffsetstore.OffsetStorePostgres, MongoDB
Implement any interface to plug in your own backend.

Engine

The eGo Engine manages entity lifecycle, wires persistence, and optionally enables clustering. Create an engine with ego.NewEngine(name, eventStore, options...), then call Start and Stop to manage its lifecycle.
OptionPurpose
WithSnapshotStore(store)Enable snapshot-based recovery
WithSnapshotInterval(n)Snapshot every n events
WithTelemetry(telemetry)Enable OpenTelemetry traces and metrics
WithLogger(logger)Pluggable structured logging
WithEncryption(encryptor)At-rest encryption for events and snapshots
WithCluster(...)Distribute entities across nodes via GoAkt clustering

Entity spawn options

OptionPurpose
WithSnapshotInterval(n)Snapshot every n events for this entity
WithBatchThreshold(n)Flush after n accumulated events
WithBatchFlushWindow(d)Flush after duration d, whichever comes first
WithRetentionPolicy(policy)Auto-cleanup of old events and snapshots

Clustering

eGo delegates clustering to GoAkt. Use WithCluster to distribute entities across nodes. Entities are partitioned by identity and placed on nodes transparently. Commands are routed by the framework.

Event batching

Under concurrent load, individual store writes become a throughput bottleneck. Event batching accumulates events across commands and flushes in a single write. While a batch is written, incoming commands are stashed and replayed after the write completes. A threshold of 0 (default) disables batching.
Write latencyRecommended threshold
< 100us (in-memory)Disabled
100us–1ms5–10
1ms–10ms10–50
> 10ms50–100

Projections

Projections consume persisted events and build read models. They track progress via an offset store and support retry, dead-letter handling, and rebuild.
CapabilityDescription
Offset trackingResumes from the last committed offset
Dead lettersCaptures failures after retry exhaustion
RebuildEngine.RebuildProjection() from a chosen point in time
Lag monitoringEngine.ProjectionLag() per shard with OTel metrics
Event adaptersSchema evolution during consumption
DecryptionAutomatic decryption before handler processing

Event publishing

eGo provides publisher APIs for pushing domain changes to external systems.
PublisherModelConnectors
EventPublisherEvent-sourced eventsKafka, Pulsar, NATS, WebSocket
StatePublisherDurable-state updatesKafka, Pulsar, NATS, WebSocket

Sagas

Sagas coordinate long-running workflows across multiple entities with compensation for failures. Saga state is persisted using the same event-sourced foundations. Start a saga with Engine.Saga() and inspect it with Engine.SagaStatus(). Define compensation logic for timeouts and failures within your saga behavior.

Event adapters

Event adapters transform persisted events during replay and projection consumption, enabling schema evolution without data migration. Register transforms via the eventadapter package.

Encryption

eGo supports at-rest encryption of events and snapshots for GDPR and compliance requirements. Enable with WithEncryption(encryptor) on the engine. Use Engine.EraseEntity(entityID) for GDPR-style data erasure.

Observability

When configured with WithTelemetry(), eGo emits OpenTelemetry traces and metrics:
SignalWhat is measured
TracesCommand processing, persistence writes
MetricsCommand counters, latency histograms, persisted events, active entities
ProjectionsProcessing counters, lag, latest offset, events-behind

Testkit

eGo ships a scenario-based testkit for validating behaviors without a running store. Use testkit.New for event-sourced and testkit.NewDurableState for durable-state behaviors with a Given/When/Then API.

See also