Skip to content

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.Money and a ban on float64 money fields.
  • Tenant-scoped idempotency keys.
  • AuthZ at the command boundary, with DenyByDefault.
  • Shared-schema tenancy with tenant_id, UniqueScope and PartitionKey helpers.
  • A per-aggregate hash chain over events.
  • Audit metadata on every command through Meta and AuditOf.
  • 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.

Docs track the go-sequent library. When APIs drift, the source wins.