dovecote
A holder. A recipient.
— Ursula K. Le Guin, “The Carrier Bag Theory of Fiction” (1986)
dovecote is a transactional outbox for Rust applications. It writes a
validated CloudEvents-compatible event in the same database transaction as
application state, then keeps its delivery state for an application-owned
worker. In schema version 2, durable event identity is scoped to the tenant
handle as (tenant_id, source, id).
Claims are leased, and only the matching claim token can change a delivery.
Delivery is at least once. For one tenant, consumers can deduplicate on
(source, id); a shared destination must include the tenant routing domain.
Your application runs the worker, chooses the transport, and applies
migrations. Dovecote promises neither FIFO nor exactly-once delivery.
[!WARNING] Dovecote is pre-release (
0.2.x). Expect the Rust API, durable schema, and migration tooling to change before v1. Backend support is version-specific; see the support matrix. Existing Keepsake deployments on MariaDB use the documented maintenance-window migration route.
A transaction
Build the event, then enqueue it in the transaction that owns the application change:
use ;
use PostgresDovecote;
use PgPool;
async
The commit makes the application change and event visible together. Publication happens later, through a worker owned by the application.
The core dovecote crate is synchronous and has no runtime or SQLx dependency.
Its SQLx adapters support PostgreSQL, MySQL/MariaDB, and SQLite without hiding
their different transaction, locking, clock, or migration behaviour.
Documentation
- SPEC.md defines the contract.
- Operations, recovery, and the support matrix cover production use.
- Integration mappings cover HTTP, Kafka, NATS JetStream, Azure Event Grid, and Debezium.
- The migration runbook moves existing Keepsake and Gatekeep data into Dovecote.
- 1.0 readiness, contributing, and security cover the project itself.
Development
The project uses the tools pinned in .mise.toml:
Licensed under MIT OR Apache-2.0.