Hexeract
Hexeract: the batteries-included messaging framework for Rust.
In-process mediator (CQRS), external message bus (RabbitMQ) and a transactional outbox/inbox, unified in a single coherent SDK with compile-time guarantees.
Hexeract is a server-side messaging framework written in Rust. It unifies in-process mediator handlers, external message bus transports, and a transactional outbox/inbox in a single coherent SDK. The framework relies on Rust's type system and procedural macros to provide compile-time guarantees in place of runtime reflection.
Hexeract is sponsored by Nubster.
What do you need?
| You need... | Reach for | Crate |
|---|---|---|
| Reliable event delivery tied to your DB transaction | Transactional outbox | hexeract-outbox |
| A SQL outbox on Postgres, MySQL or SQLite | SQL backends | hexeract-outbox-sql |
| In-process command/query dispatch (CQRS) | Mediator | hexeract-mediator |
| Publish and consume over a broker | Message bus | hexeract-bus |
| A RabbitMQ transport | AMQP backend | hexeract-bus-rabbitmq |
| Everything wired together | Umbrella facade | hexeract |
Status
🛡️ v0.5.0: reliability hardening shipped. This release closes the delivery-reliability gaps in the outbox and the RabbitMQ bus: durable poison-message handling with opt-in dead-lettering, dispatch outside the database transaction, bounded exponential backoff with jitter, publisher confirms, bounded consumer buffers and a deadline/cancellation-safe shutdown. The legacy hexeract-outbox-postgres crate has been removed in 0.5.0; use hexeract-outbox-sql with the postgres feature instead. Mediator, middlewares, the #[handler] macro and Bus RabbitMQ stay stable from v0.3.0.
| Feature | v0.1.0 | v0.2.0 | v0.3.0 | v0.4.0 | v0.5.0 |
|---|---|---|---|---|---|
| Transactional outbox (PostgreSQL) | ✅ | ✅ | ✅ | ✅ | ✅ |
Worker poll loop with SKIP LOCKED |
✅ | ✅ | ✅ | ✅ | ✅ |
| Fluent builder API | ✅ | ✅ | ✅ | ✅ | ✅ |
hexeract outbox CLI |
✅ | ✅ | ✅ | ✅ | ✅ |
Bus core (Message, BusEnvelope, Transport, Handler<M>) |
⏳ | ✅ | ✅ | ✅ | ✅ |
RabbitMQ backend (lapin connection pool, publish, consume, retry) |
⏳ | ✅ | ✅ | ✅ | ✅ |
Topology types (Exchange, Queue, Binding, RoutingKey) |
⏳ | ✅ | ✅ | ✅ | ✅ |
hexeract bus declare / peek / purge CLI |
⏳ | ✅ | ✅ | ✅ | ✅ |
In-process CQRS mediator (send, query, publish) |
⏳ | ⏳ | ✅ | ✅ | ✅ |
Built-in TracingMiddleware and TimeoutMiddleware |
⏳ | ⏳ | ✅ | ✅ | ✅ |
#[handler] attribute macro with verify_handlers() |
⏳ | ⏳ | ✅ | ✅ | ✅ |
Multi-database outbox (hexeract-outbox-sql: PostgreSQL, MySQL, SQLite) |
⏳ | ⏳ | ⏳ | ✅ | ✅ |
| Delivery reliability (dead-letter, publisher confirms, bounded backoff, dispatch outside tx) | ⏳ | ⏳ | ⏳ | ⏳ | ✅ |
| Polyglot bus (NATS, Kafka, SQS) | ⏳ v0.9.0 | ⏳ v0.9.0 | ⏳ v0.9.0 | ⏳ v0.9.0 | ⏳ v0.9.0 |
| Sagas, Scheduler, Request and Reply | ⏳ later | ⏳ later | ⏳ later | ⏳ later | ⏳ later |
See the CHANGELOG for the detailed history.
Quick start
Outbox (PostgreSQL)
Add the umbrella crate with the outbox-sql-postgres feature to your Cargo.toml (outbox-sql-mysql and outbox-sql-sqlite ship the same surface):
[]
= { = "0.5", = ["outbox-sql-postgres"] }
Power users who prefer a strict SemVer per crate can keep depending on
hexeract-outbox,hexeract-outbox-sql,hexeract-bus,hexeract-bus-rabbitmqetc. directly.
Declare a domain event, a handler and wire a worker:
use Duration;
use HandlerContext;
use ;
use ;
use ;
use CancellationToken;
use Uuid;
;
# async
See docs/tutorial/getting-started.md for the full integration walkthrough.
Bus (RabbitMQ)
Add the umbrella crate with the bus-rabbitmq feature to your Cargo.toml:
[]
= { = "0.5", = ["bus-rabbitmq"] }
Declare a domain message, a handler and wire a publisher plus a worker:
use ;
use ;
use HandlerContext;
use ;
use CancellationToken;
use Uuid;
;
# async
In production, declare your topology once at service startup (or out of band through the CLI). The
topology::ensure_topologyhelper and the CLI live for dev convenience; do not call them on the hot path.
The hexeract bus CLI provisions and inspects a broker without writing ad-hoc lapin scripts:
# 1. Apply a typed topology described in TOML.
# 2. Peek the first messages of a queue (non-destructive, requeues each delivery).
# 3. Drop every message in a queue (gated by an explicit safety flag).
See the runnable crates/hexeract-examples/examples/03_bus_pubsub.rs for an end-to-end pub/sub against a real RabbitMQ container, and crates/hexeract-cli/examples/topology.toml for the topology file format consumed by hexeract bus declare.
Mediator (in-process)
Add the umbrella crate with the mediator feature to your Cargo.toml:
[]
= { = "0.5", = ["mediator"] }
Register a command handler and dispatch through the mediator:
use ;
use MediatorBuilder;
;
# async
Queries (Mediator::query) and notifications (Mediator::publish) follow the same pattern. Notifications fan out to every handler registered for the type in registration order; failures are aggregated so siblings keep running. Wire your own [Middleware] implementations through MediatorBuilder::with_middleware to add tracing, timeouts or any cross-cutting behavior around every dispatch.
Why Hexeract
Building event-driven services in Rust today means manually wiring a broker client, an outbox table, and an in-process dispatch layer together. Hexeract closes that gap with a single SDK that covers the full shipped surface while keeping each feature independently usable:
- Mediator, dispatch commands to handlers in-process, type-safe and reflection-free.
- Bus, publish and consume over a message broker through a unified transport abstraction.
- Outbox, save business state and outgoing messages atomically in a single database transaction.
The bet behind Hexeract is that Rust's compile-time guarantees turn the outbox pattern from a vigilance discipline into something the type system enforces.
Roadmap
Available today: Mediator, Bus, Outbox/Inbox, and delivery reliability (dead-letter handling, publisher confirms, idempotency).
Planned: Sagas, Scheduler, Request/Reply. See ROADMAP.md.
What Hexeract is not
To stay focused, the following are explicitly out of scope:
- Not a service mesh. No automatic mTLS or network policies between services. Use Linkerd or Istio.
- Not a broker. Hexeract is a client; you keep your existing RabbitMQ, NATS or Kafka.
- Not a standalone workflow engine. Sagas live inside your services, not in a dedicated cluster. Use Temporal or Airflow when you need that shape.
- Not an event streaming engine. No real-time stream processing. Use Kafka Streams or Apache Flink.
Audience
- Rust backend teams building microservices who want a cohesive messaging toolkit instead of stacking incompatible crates.
- Developers migrating to Rust looking for a cohesive messaging SDK.
- Polyglot teams with part of their stack moving to Rust and the need to stay interoperable on a shared bus alongside their Node, Python or Go services.
Contributing
Contributions are welcome. Please read CONTRIBUTING.md first for the workflow and conventions, and CODE_OF_CONDUCT.md for the community guidelines. For vulnerability reports, see SECURITY.md. For open-ended questions and design conversations, use GitHub Discussions.
Stability and versioning are documented in docs/SEMVER_POLICY.md and docs/MSRV_POLICY.md.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.
See CONTRIBUTING.md for details, including the Contributor License Agreement (CLA).
Copyright © Nubster.