eventsalsa/store
Append-only event storage with optimistic concurrency and a transaction-first API.
Read more →Build around the pieces you need today and grow into the rest when the system demands it.
Append-only event storage with optimistic concurrency and a transaction-first API.
Read more →Run async projections across one or more daemon instances, with PostgreSQL-backed rebalancing.
Read more →Standalone envelope encryption for PII and secrets, with crypto-shredding and HMAC hashing for sensitive lookups.
Read more →Keep the architecture explicit, the runtime PostgreSQL-native, and the domain model free of framework ownership.
Use only the modules you need. The store, projector, and encryption packages can be adopted independently.
eventsalsa does not require aggregate root base types or framework-owned structs in your domain model.
Expected versions make concurrent writes explicit and keep aggregate updates honest.
The store and projector are built on PostgreSQL - no need for a 3rd party message broker.
Versioned events support rich domain modelling while keeping the model explicit and free from framework-owned types.
Keep event infrastructure at the edges while the application model remains plain Go.
eventsalsa/store gives you an append-only event log, optimistic
concurrency, and a transaction-first API without prescribing your domain model.
go get github.com/eventsalsa/store pgx.Tx you already have. import ( "time" "github.com/eventsalsa/store" "github.com/eventsalsa/store/postgres" "github.com/google/uuid")s := postgres.NewStore(postgres.DefaultStoreConfig())event := store.Event{ StreamType: "User", StreamID: userID, EventID: uuid.New(), EventType: "UserRegistered", EventVersion: 1, Payload: payload, Metadata: []byte(`{}`), CreatedAt: time.Now(),}if _, err := s.Append(ctx, tx, store.NoStream(), []store.Event{event}); err != nil { return err} type AccountProjection struct{}func (p *AccountProjection) Name() string { return "account_projection"}func (p *AccountProjection) Handle(ctx context.Context, tx pgx.Tx, event store.PersistedEvent) error { return nil}daemon := projector.New( db, eventStore, []projector.Projection{ projector.FilterStreamTypes(&AccountProjection{}, "Account"), }, projector.WithBatchSize(100), projector.WithPollInterval(500 * time.Millisecond),)if err := daemon.Start(ctx); err != nil { return err} eventsalsa/projector runs async projections across one or
more daemon instances, with PostgreSQL-backed assignment and rebalancing.
go get github.com/eventsalsa/projector projector.FilterStreamTypes without requiring a separate broker.