72 releases (14 stable)
| new 1.8.0 | Dec 15, 2025 |
|---|---|
| 1.7.2 | Nov 11, 2025 |
| 1.5.1 | Oct 25, 2025 |
| 1.0.4 |
|
| 0.0.2 | Jun 19, 2022 |
#225 in Database interfaces
Used in timada-market
150KB
3.5K
SLoC
Evento
A collection of libraries and tools that help you build DDD, CQRS, and event sourcing applications in Rust.
More information about this crate can be found in the crate documentation.
Features
- Event Sourcing: Store state changes as immutable events with complete audit trail
- CQRS Pattern: Separate read and write models for scalable architectures
- SQL Database Support: Built-in support for SQLite, PostgreSQL, and MySQL
- Event Handlers: Async event processing with automatic retries
- Event Subscriptions: Continuous event stream processing
- Event Streaming: Real-time event streams (with
streamfeature) - Snapshots: Periodic state captures to optimize aggregate loading
- Database Migrations: Automated schema management
- Macro Free API: Clean, macro-free API (macros available optionally)
- Type Safety: Fully typed events and aggregates with compile-time guarantees
Usage Example
use evento::{EventDetails, AggregatorName};
use serde::{Deserialize, Serialize};
use bincode::{Decode, Encode};
// Define events
#[derive(AggregatorName, Encode, Decode)]
struct UserCreated {
name: String,
email: String,
}
#[derive(AggregatorName, Encode, Decode)]
struct UserEmailChanged {
email: String,
}
// Define aggregate
#[derive(Default, Serialize, Deserialize, Encode, Decode, Clone, Debug)]
struct User {
name: String,
email: String,
}
// Implement event handlers on the aggregate
#[evento::aggregator]
impl User {
async fn user_created(&mut self, event: EventDetails<UserCreated>) -> anyhow::Result<()> {
self.name = event.data.name;
self.email = event.data.email;
Ok(())
}
async fn user_email_changed(&mut self, event: EventDetails<UserEmailChanged>) -> anyhow::Result<()> {
self.email = event.data.email;
Ok(())
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Setup SQLite executor
let pool = sqlx::SqlitePool::connect("sqlite:events.db").await?;
let mut conn = pool.acquire().await?;
// Run migrations
evento::sql_migrator::new_migrator::<sqlx::Sqlite>()?
.run(&mut *conn, &evento::migrator::Plan::apply_all())
.await?;
let executor: evento::Sqlite = pool.into();
// Create and save events
let user_id = evento::create::<User>()
.data(&UserCreated {
name: "John Doe".to_string(),
email: "john@example.com".to_string(),
})?
.metadata(&true)?
.commit(&executor)
.await?;
// Update user
evento::save::<User>(&user_id)
.data(&UserEmailChanged {
email: "newemail@example.com".to_string(),
})?
.metadata(&true)?
.commit(&executor)
.await?;
// Load aggregate from events
let user = evento::load::<User, _>(&executor, &user_id).await?;
println!("User: {:?}", user.item);
Ok(())
}
Event Handlers and Subscriptions
use evento::{Context, EventDetails, Executor};
// Define a handler function
#[evento::handler(User)]
async fn on_user_created<E: Executor>(
context: &Context<'_, E>,
event: EventDetails<UserCreated>,
) -> anyhow::Result<()> {
println!("User created: {} ({})", event.data.name, event.data.email);
// Trigger side effects, send emails, update read models, etc.
Ok(())
}
// Subscribe to events
evento::subscribe("user-handlers")
.handler(on_user_created())
.run(&executor)
.await?;
Feature Flags
macro(enabled by default) Enable procedural macros for cleaner codehandler(enabled by default) Enable event handlers with retry supportstreamEnable streaming support withtokio-streamgroupEnable event grouping functionalitysqlEnable all SQL database backends (SQLite, MySQL, PostgreSQL)sqliteSQLite support via sqlxmysqlMySQL support via sqlxpostgresPostgreSQL support via sqlx
Minimum Supported Rust Version
Evento's MSRV is 1.75.
Safety
This crate uses #![forbid(unsafe_code)] to ensure everything is implemented in 100% safe Rust.
Examples
The examples directory contains sample applications demonstrating various features:
- todos - A complete todo application with CQRS, demonstrating command/query separation and event handlers
Getting Help
If you have questions or need help, please:
- Check the documentation
- Look at the examples
- Open an issue on GitHub
License
This project is licensed under the Apache-2.0 license.
Dependencies
~3–22MB
~239K SLoC