Tito
A transactional outbox with partitioned pub/sub and scheduled event processing, built on TiKV.
What It Does
When you save data, events are written in the same transaction. Workers pick them up later. No dual-write problem, no lost messages.
┌─────────────────────────────────────────────────────────────────┐
│ Your App │
│ │
│ model.create(user) ──► TiKV Transaction: │
│ 1. Write user data │
│ 2. Write event (same tx) │
│ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ TiKV │
│ │
│ data:user:123 ─────────────► { id, name, email } │
│ event:user:0001:1732541234:abc ──► { entity, action, ... } │
│ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Workers │
│ │
│ Worker 1 (partition 0) ──► Pulls events, processes, acks │
│ Worker 2 (partition 1) ──► Pulls events, processes, acks │
│ Worker N (partition N) ──► ... │
│ │
└─────────────────────────────────────────────────────────────────┘
Features
- Transactional Outbox: Events written atomically with data
- Horizontal Partitioning: Scale by adding partitions and workers
- Scheduled Processing: Set
timestampfor when events should fire - Pub/Sub Semantics: Workers subscribe to event types
- Checkpointed: Resume from where you left off after crashes
Quick Start
Define a Model
Create Data (Events Generated Automatically)
let db = connect.await?;
let user_model = db.clone.;
db.transaction.await?;
Run Workers
let queue = new;
let partition_config = new;
run_worker.await;
Event Key Format
event:{type}:{partition}:{timestamp}:{uuid}
type: Event name fromevents()(e.g., "user", "order")partition: 4-digit partition number (0000-9999)timestamp: Unix timestamp for scheduled processinguuid: Unique event ID
Scaling
Add partitions and workers. Each worker owns one partition:
// Worker 1
new // 4 total, owns partition 0
// Worker 2
new // 4 total, owns partition 1
// Worker 3
new // 4 total, owns partition 2
// Worker 4
new // 4 total, owns partition 3
Need more throughput? Increase total_partitions and add workers.
Scheduled Events
Set timestamp in the future for delayed processing:
Workers only process events where timestamp <= now.
Requirements
- Rust 2021+
- TiKV cluster
License
Apache-2.0