#event-sourcing #cqrs #aggregate #ddd


Event sourcing and CQRS for Rust applications

4 releases (breaking)

0.4.0 May 23, 2020
0.3.0 May 17, 2020
0.2.0 May 16, 2020
0.1.0 May 10, 2020

#4 in #aggregate


1.5K SLoC


Latest Release Documentation License Rustc Support 1.39+ Build Status

Event sourcing and CQRS for Rust applications

very much work in progress!

eventmill = "0.4"

to use the derive macros from the eventmill-derive crate activate the derive feature:

eventmill = { version = "0.4", features = ["derive"] }    

Usage example

Define your domain events:

const EVENT_NAMESPACE: &str = "https://github.com/innoave/eventmill/examples/counter";

#[derive(EventType, Debug, Clone, PartialEq)]
struct Incremented;

Define your aggregate:

#[derive(AggregateType, Debug)]
struct Counter {
    id: i32,
    hits: u64,

Implement the business logic for applying events to the aggregate:

impl Aggregate<Incremented> for Counter {
    fn apply_event(&mut self, _event: &DomainEvent<Incremented, Self>) {
        self.hits += 1;

Define a command:

#[derive(Debug, PartialEq)]
struct Increment;

Implement the business logic so that the aggregate is able to handle the command:

impl HandleCommand<Increment, Self> for Counter {
    type Event = Incremented;
    type Error = Infallible;
    type Context = ();

    fn handle_command(
        _command: Increment,
        _context: &Self::Context,
    ) -> Result<Vec<NewEvent<Self::Event, Counter>>, Self::Error> {
        Ok(vec![NewEvent {
            aggregate_id: self.id,
            data: Incremented,

Bringing it all together using the Core dispatcher:

fn main() {
    let event_store = InMemoryStore::new();
    let core = Core::new(event_store);

    let aggregate_id = 4711;

    let increment_command = DomainCommand {
        aggregate_generation: Generation::default(),
        data: Increment,

    let versioned_counter: VersionedAggregate<Counter> = core
        .dispatch_command(increment_command, &())
        .expect("counter incremented");

    assert_eq!(versioned_counter.state().hits, 1);

These code samples are taken from the counter example. Take a look at eventmill-examples for more insights.


  • define basic abstractions and API
  • provide a first example on how it looks like to use the API
  • make more examples to polish the API
  • write rust-doc for the API
  • support async/await or switch to async as the only option
  • consider providing default implementations for eventstores and other building blocks
  • ...


~44K SLoC