Reference
go-sequent vs Sequent (Ruby)
How go-sequent relates to Ruby's Sequent: concept mapping, what is implemented in Go, what differs (context-scoped UnitOfWork, decimal money, hash chain) and what is deliberately not ported.
go-sequent vs Sequent (Ruby)
Sequent is an opinionated CQRS and event sourcing framework for Ruby. go-sequent borrows its concepts and its vocabulary, and builds a Go-native library for financial ledgers. This page shows how the two map and where they differ.
go-sequent is not a port, not wire-compatible, and not database-compatible. It never reads or imports a Ruby Sequent database.
Concept mapping
| Sequent (Ruby) | go-sequent |
|---|---|
Sequent::Command with attrs and ActiveModel validations |
Command interface; Validate() error on the command |
Sequent::Event with attrs |
Event interface; structs embed event.Base, registered by type name |
Sequent::AggregateRoot with on Event do |
Embed aggregate.Base; On(sample, applier); command methods call Apply |
CommandHandler with on Command do |
command.Handler with Handles() and Handle(); routed by command type string |
CommandService with a thread-local queue |
command.Service; one txn and one context-scoped UnitOfWork per Execute |
AggregateRepository (thread UoW, identity map) |
aggregate.Repository bound to a UnitOfWork on context |
EventStore with PL/pgSQL store_events |
eventstore.Store; the Postgres store follows the same lock-and-sequence logic |
Projector with a Persistor |
projector.Projector with ManagedTables and projector.Persistor |
Workflow with after_commit |
workflow.Workflow and workflow.RegisterAfterCommit |
Sequent.configure globals |
sequent.New and sequent.App, built explicitly |
| Command middleware and filters | command.Middleware chain and command.Filter |
| Snapshots via Marshal | Versioned JSON snapshots |
| Unique keys | UniqueKeys() on the aggregate, stored in aggregate_unique_keys |
| Migrations and projector replay | go-sequent migrate and projector/replay (prepare, replay, catchup, optimize, golive) |
| Autoregistration of handlers | Explicit Register* calls |
What is implemented
Implemented with Go APIs: AggregateRoot, Command, Event, CommandService, Repository, EventStore, Projector, Workflow, snapshots, upcasters, migrations and the replay pipeline.
The basic flow is the same. A command opens one transaction. Handlers load or create aggregates through the repository, and aggregates apply events. The repository commits events and publishes them to projectors and workflows in the same transaction by default.
Where go-sequent differs
Concurrency model
Ruby Sequent keeps its UnitOfWork per thread. Go uses a UnitOfWork stored in context.Context, one per Execute. Sharing it across goroutines is forbidden. Parallelism comes from independent requests, rebuild workers and asynchronous consumers, not from inside one command.
Finance features
These go beyond Sequent and are first-class in go-sequent:
- Decimal
types.Moneyand a ban onfloat64money fields. - Tenant-scoped idempotency keys.
- AuthZ at the command boundary, with
DenyByDefault. - Shared-schema tenancy with
tenant_id,UniqueScopeandPartitionKeyhelpers. - A per-aggregate hash chain over events.
- Audit metadata on every command through
MetaandAuditOf. - Tombstone hooks for GDPR.
- Optional OpenTelemetry on the write path.
- An optional outbox drained by Postgres polling.
Publishing
Ruby Sequent’s default is synchronous projectors in the write transaction. go-sequent keeps that as SyncInTxn and requires it for ledgers. For asynchronous paths there is an outbox polled from a Postgres table. There is no LISTEN/NOTIFY mode and no bus.
Event integrity
go-sequent hashes every stored event into a chain. It does not sign events. Sequent has no equivalent.
What is not ported
| Sequent (Ruby) | go-sequent |
|---|---|
| ActiveRecord records and migration DSL | None. Projectors declare ManagedTables and rebuild through projector/replay. |
| Rails or Sinatra generators and autoregistration | None. It is a pure library. |
| AggregateObserver | Not provided |
| ValueObject type system | Plain Go structs plus types.Money |
| Default message bus, LISTEN/NOTIFY | Optional outbox polling |
Sequent::Secret (BCrypt) |
Not a framework feature; keep password hashing in your application |
| Event signatures | Out of scope. The hash chain provides tamper detection. |
| Importing a Sequent database | Never |
| HTTP or gRPC | None |
Migrating from a Ruby Sequent system
There is no data migration path from a Ruby Sequent database. If you are moving a system, replay your business history through your own tooling by issuing commands to go-sequent, or run the systems side by side and cut over at a business boundary. Do not load Ruby Sequent SQL dumps into go-sequent schemas.
Related
Docs track the go-sequent library. When APIs drift, the source wins.