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

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.
// 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.
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.
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.
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.
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.
Microservice-architectuur
goes vormt de ruggengraat voor event-driven microservicesystemen. Elke service communiceert via de centrale eventbus. Scroll om elke component te verkennen.
Domain Entities die Business Logic inkapselen en Invariants afdwingen. Het Aggregate is de Consistency Boundary voor events.
Scroll om de architectuur te verkennen
1 / 8
Tech Stack
Battle-Tested in echte projecten
goes is niet academisch. Het framework ontstond uit de noodzaak om complexe Domain Logic netjes te modelleren en wordt sinds 2021 in Production ingezet.
Crovillas
Platform voor luxe villa's met Event-Sourced Booking Engine, Multi-App Architecture en gRPC Microservices.
DepositDirect
Huurwaarborgplatform met Event-Sourced Payment Flows, Aggregate-gebaseerd waarborgbeheer en CQRS Read Models.
Prestige Cars
Luxury Car Rental met Event-Sourced Fleet Management, Booking Aggregates en Real-Time Projections.
... en vele andere Production Systems die op goes zijn gebouwd
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.