Open Source Framework

goes

Type-safe Aggregates, Commands en Projections - van prototyping tot Production.

158 ·Apache-2.0· Go ·17 forks
goes Gopher
Scroll
Overzicht

Wat is goes?

goes is een Event-Sourcing Framework voor Go dat de bouwstenen biedt voor gedistribueerde, eventgebaseerde applicaties. Type-safe Aggregates, Commands en Projections - met verwisselbare backends voor elke schaalgrootte.

In tegenstelling tot veel Event-Sourcing Libraries die óf te academisch óf te opinionated zijn, kiest goes voor idiomatic Go. Geen codegeneratie, geen magische annotations - alleen Interfaces, Generics en Composition. Je definieert je Aggregates als gewone Go-Structs, registreert Event Handlers via getypeerde functies, en het framework verzorgt Persistence, Replay en Concurrency.

goes is bedoeld voor Go-teams die Event Sourcing en CQRS willen integreren in bestaande of nieuwe systemen, zonder gebonden te zijn aan een specifieke infrastructuursetup. Of je nu met een eenvoudig In-Memory Prototype start of een gedistribueerd systeem met NATS, MongoDB en PostgreSQL beheert, de Domain Logic blijft identiek.

In actie
order.go
// Define your aggregate
type Order struct {
    *aggregate.Base

    Items  []LineItem
    Status OrderStatus
}

// Register typed event handlers
func NewOrder(id uuid.UUID) *Order {
    o := &Order{Base: aggregate.New("order", id)}

    event.ApplyWith(o, o.placed, "order.placed")
    event.ApplyWith(o, o.paid, "order.paid")

    return o
}

// Produce events from commands
func (o *Order) Place(items []LineItem) error {
    aggregate.Next(o, "order.placed",
        OrderPlaced{Items: items},
    )
    return nil
}

// Rebuild state from events
func (o *Order) placed(e event.Of[OrderPlaced]) {
    o.Items = e.Data().Items
    o.Status = Placed
}

Geen codegeneratie, geen annotations - alleen Go Interfaces, Generics en Composition. De Domain Logic blijft schoon en portable.

Motivatie

Waarom Event Sourcing?

Het probleem

Traditionele CRUD-systemen slaan alleen de huidige State op. Als er een fout optreedt of een audit nodig is, ontbreekt de historie. Data wordt overschreven, context gaat verloren. Wie heeft wat wanneer en waarom gewijzigd? Deze vragen zijn niet te beantwoorden met een klassiek UPDATE-statement.

De aanpak

Event Sourcing slaat elke State Change op als event. De huidige State wordt gereconstrueerd uit de Event History. Niets gaat verloren: volledige Audit Trails, Time-Travel Debugging en de mogelijkheid om nieuwe Read Models met terugwerkende kracht uit bestaande events op te bouwen. Je Event Log wordt de Single Source of Truth.

Wat goes anders maakt

goes neemt de complexiteit uit Event Sourcing in Go. Geen boilerplate, geen DSLs - alleen Go-Interfaces en Generics. Je start met In-Memory Backends en schakelt over naar MongoDB, PostgreSQL of NATS zonder één regel Domain-Code te wijzigen. Het framework verzorgt Event Routing, Aggregate Hydration, Snapshot Management en Projection Scheduling. Jij focust je op je domein.

Zo werkt het

De Event Pipeline

Elke State Change stroomt door een duidelijk gedefinieerde pipeline. Commands activeren Aggregate Logic, die events produceert. Events worden gepersisteerd en naar Read Models geprojecteerd.

1
Command

Een getypeerde Intent wordt gedispatched en via een Middleware Chain gevalideerd.

2
Aggregate

Het Aggregate dwingt invarianten af en produceert events uit commands.

3
Event

Een Immutable Fact die een State Change beschrijft. Single Source of Truth.

4
Event Store

Events worden append-only gepersisteerd en naar subscribers verdeeld.

5
Projection

Read Models worden opgebouwd uit de Event Stream, live of on-demand.

Architectuur

Core Concepts

Event-Sourced Aggregates

Base-Type embedden, getypeerde Event Handlers registreren. Versioning, Persistence en Replay worden door het framework verzorgd. Aggregates zijn gewone Go-Structs met een embedded aggregate.Base. Event Handlers worden via een Generic-functie geregistreerd en bij Hydration automatisch aangeroepen. Soft-Deletes, Aggregate-Versioning en Optimistic Concurrency Control zijn out of the box inbegrepen.

Distributed Events

Events publishen en subscriben via NATS JetStream. MongoDB en PostgreSQL als Event Stores. Backends wisselen zonder codewijzigingen. De Event Bus abstraheert Transport en Delivery. Je code werkt met getypeerde events, ongeacht of deze lokaal, in-process of verspreid over een cluster zijn.

Type-Safe Commands

Commands dispatchen en afhandelen met volledige Generic-Type-Safety. Synchroon of asynchroon, afhankelijk van de use case. De Command Bus ondersteunt Middleware, Context Propagation en Error Handling. Asynchrone Commands worden via de Event Bus gedispatched, synchrone direct in het Process.

Projection Toolkit

Read Models bouwen met Continuous of Periodic Schedules. Automatische Progress-Tracking, Debouncing en Startup-Catch-up. Projections kunnen uit elke Event Store lezen en naar willekeurige Read-Databases schrijven. De Scheduler verzorgt Error-Retry, Backoff en gegarandeerde Processing.

Codec Registry

Event-namen op Go-Types mappen voor automatische serialisatie. JSON als default, MessagePack of Protobuf als One-Line-Swap. De Codec Registry staat centraal voor type-safe Event Handling. Ze zorgt ervoor dat events correct worden geserialiseerd, gedeserialiseerd en geversioneerd.

Snapshots

Aggregate State op een bepaald moment capturen. Alleen recente events replayen in plaats van de volledige historie. Snapshots worden automatisch aangemaakt na configureerbare intervallen. MongoDB, PostgreSQL en In-Memory Stores worden ondersteund, met dezelfde Pluggable-Backend-architectuur als de Event Store.

Testable by Design

Fluent Test-Assertions voor Aggregates, In-Memory Backends voor Integration Tests en Conformance Suites voor Custom Implementations. Het Testing-package biedt Expect-Style Assertions: given Events, when Command, then Events. Conformance Suites zorgen ervoor dat Custom Event Store Implementations zich correct gedragen.

Modulair ontwerp

Gebruik alleen wat nodig is - Event System, Commands, Projections - en voeg andere Components naar behoefte toe. Elk package heeft duidelijk gedefinieerde interfaces en minimale dependencies. Je kunt goes stapsgewijs in een bestaand project integreren, zonder alles tegelijk te hoeven overnemen.

Backends

Production-Ready Backends

goes volgt het principe van verwisselbare backends: elke Event Store, Snapshot Store en Event Bus implementeert een gezamenlijke interface. Je ontwikkelt tegen Abstractions, niet tegen Implementations. Hierdoor kun je lokaal testen met In-Memory Backends, in Staging MongoDB gebruiken en in Production PostgreSQL met NATS inzetten, zonder één regel Domain-Code aan te passen.

MongoDB

Documentgebaseerde Event Store met native Change-Stream-ondersteuning voor Real-Time Event Subscriptions. Ideaal voor Event-Driven Architectures waarbij Projections in realtime op nieuwe events moeten reageren. Ondersteunt ook snapshots en optimistische concurrency via Document Versioning.

PostgreSQL

Relationele Event Store met ACID-transacties en Optimistic Concurrency Control. Perfect voor teams die al een PostgreSQL-setup hebben en geen extra infrastructuur willen introduceren. Serializable Isolation garandeert consistente Event Streams.

NATS JetStream

Distributed Event Bus met At-Least-Once Delivery, Consumer Groups en horizontale schaling. NATS is bijzonder geschikt voor microservice-architecturen waarbij events tussen services moeten worden verdeeld. Persistence via JetStream, replay via Consumer Offsets.

In-Memory

Zero-config backend voor prototyping en testing. Dezelfde API als Production Backends, zodat tests en prototypes dezelfde code gebruiken als in Production. Geen setup, geen dependencies, direct klaar.

Interactief 3D

Microservice-architectuur

goes vormt de ruggengraat voor event-driven microservicesystemen. Elke service communiceert via de centrale eventbus. Scroll om elke component te verkennen.

Aggregates1/8

Domain Entities die Business Logic inkapselen en Invariants afdwingen. Het Aggregate is de Consistency Boundary voor events.

Technologie

Tech Stack

Go NATS JetStream MongoDB PostgreSQL Protocol Buffers gRPC Docker
GitHub
158

GitHub Stars

Licentie

Apache-2.0

Taal

Go

Forks

17

Contributors

5+

Bekijken op GitHub

FAQ

Veelgestelde vragen over goes

Ja. goes wordt in meerdere Production Systems gebruikt en actief onderhouden. Het framework heeft een stabiele API en wordt intern bij modernice gebruikt voor klantprojecten. Projecten zoals Crovillas, DepositDirect en Prestige Cars draaien sinds 2021 op goes.

goes ondersteunt MongoDB, PostgreSQL en NATS JetStream als Production Backends. Voor testing en prototyping zijn er volledige In-Memory Implementations. Alle backends implementeren dezelfde interfaces, wat een wissel zonder codewijzigingen mogelijk maakt.

Basiskennis van Go is voldoende. De Getting-Started Guide en de tutorial van 12 hoofdstukken leiden je stap voor stap door alle concepten. goes is zo ontworpen dat je Event Sourcing Patterns incrementeel kunt leren en toepassen.

Ja. goes is modulair opgebouwd. Je kunt afzonderlijke Components zoals het Event System of Commands onafhankelijk gebruiken en andere naar behoefte integreren. Er is geen All-or-Nothing Dependency.

goes is ontworpen voor High-Throughput Scenarios. Snapshots verkorten de Replay-tijd drastisch, Projections draaien asynchroon en geparalleliseerd, en de Event Store ondersteunt batching. In Production worden meerdere miljoenen events zonder merkbare latentie verwerkt.

EventStoreDB is een zelfstandige database, terwijl goes je bestaande infrastructuur gebruikt (MongoDB, PostgreSQL, NATS). Axon is Java-gebaseerd en aanzienlijk opinionated. goes geeft je de bouwstenen en laat jou beslissen hoe je ze samenstelt. Geen runtime-dependencies buiten je gekozen backend.

goes vereist Go 1.23 of nieuwer. Het framework gebruikt Go Generics intensief voor Type-Safety bij Commands, Events en Aggregates. We raden altijd de nieuwste stabiele Go-versie aan.

Contributions zijn welkom. De beste start is de GitHub Repository. Issues met het label 'good first issue' zijn geschikt om te beginnen. PRs worden gereviewd en tijdig gemerged. Voor grotere Changes raden we aan eerst een issue aan te maken om de aanpak af te stemmen.

Neem contact met ons op

Gebruik je goes, of twijfel je of event sourcing bij je project past? Neem contact op, we praten graag over architectuur en ervaringen uit de praktijk.