ArchitectureKit
Building blocks for applications based on Domain-Driven Design, CQRS, and Event Sourcing, in Go and on top of EventSourcingDB. A kit rather than a framework – every piece can be used on its own, and nothing happens behind your back.
Open source under the MIT license.
- License
- MIT License
- Language
- Go
Two places where event-sourced applications rely on luck.
Two concurrent writes to the same thing on the way in, and a read right after a write on the way out. ArchitectureKit handles both, and it covers both sides of an application – commands, events, and state for writing, projections, views, and queries for reading.
- Every command writes with its preconditions. The database rejects duplicates and concurrent changes, not your luck.
- A read can wait for your own write. Views track the revision they have seen, and a query waits until it is reached.
- Tests need no database. A test package checks deciders, projections, and queries without a database.
var acquireBook = architecturekit.Decider[AcquireBook, Book]{
State: bookState,
Decide: func(ctx context.Context, cmd AcquireBook, book Book) ([]architecturekit.Event, error) {
if book.IsAcquired {
return nil, architecturekit.NewDomainError("book %s has already been acquired", cmd.BookID)
}
return []architecturekit.Event{
BookAcquired{Title: cmd.Title, Author: cmd.Author, ISBN: cmd.ISBN},
}, nil
},
}
A decider receives a command and the current state, and returns the events to write. Execute reads the events, evolves the state, decides, and writes.
Both sides of an event-sourced application.
Every capability links to the part of the docs that explains it.
Decisions on commands
- Commands, events, and statePlain structs, with the state evolved from the events of a subject.Defining Commands
- DecidersThe decision on a command, as a function of the command and the state.Making Decisions
- PreconditionsPrevent duplicates, guard against concurrent changes, enforce rules across subjects.Using Preconditions
- Versioned eventsUpcasters translate stored events of an old type into the new one.Versioning Events
Views that keep up
- ProjectionsTurn events into views, and resume where they stopped.Projections
- ViewsHold the data that queries read, in memory or in a database of your own.Defining Views
- QueriesFilter, order, page, and count the items of a view.Defining Queries
- Reading your own writesWait until a view has seen the events you have written.Reading Your Own Writes
An API for commands and queries
- Commands over HTTPMap requests to commands, for the user who makes them.Handling Commands over HTTP
- AuthorizationRefuse a command before it is executed.Handling Commands over HTTP
- Queries over HTTPAnswer queries in the default format, or in your own.Handling Queries over HTTP
- Status codesEvery error maps to the status code that matches it.Mapping Errors to Status Codes
Tests without a database
- DecidersGiven events, when a command, then events, a rejection, or preconditions.Testing Deciders
- UpcastersCheck the translation of old events.Testing Deciders
- ProjectionsApply stored events to a projection and inspect its view.Testing Projections
- QueriesAnswer queries against a view filled for the test.Testing Queries
Try it yourself.
Quickstart
This quickstart gets a first command running with ArchitectureKit in a few minutes: you start EventSourcingDB with Docker, define a command, an event, and the state to decide on, and execute the command. It uses a temporary setup for development and testing – for everything else, see the links at the end.
Start the quickstart →ArchitectureKit Documentation
Quickstart, Fundamentals, and Guides.
Open the docs →Planning something bigger?
Whether you need a quote, support, or a second opinion on your architecture – we are happy to help.