Maiko
Lightweight actor framework for Tokio
What is Maiko?
Maiko is an actor framework for Tokio. Structure your application as independent components - each with its own state, logic, and lifecycle - communicating purely through events.
Each actor:
- Runs in its own async task
- Maintains private state (no shared memory, no locks)
- Receives events through a dedicated mailbox
- Publishes events without knowing who receives them
Actors subscribe to topics, publish events, and Maiko routes automatically. Publishers don't need to know who's listening - think Kafka-style pub/sub, but for Tokio tasks instead of distributed systems.
No more channel spaghetti
Building concurrent Tokio applications often means manually creating, cloning, and wiring channels between tasks:
// Without Maiko: manual channel wiring
let = channel;
let = channel;
let = channel;
// Clone tx1 for task B, clone tx2 for task C, wire rx1 to...
// With Maiko: declare subscriptions, routing happens automatically
sup.add_actor?; // produces events
sup.add_actor?; // handles sensor data
sup.add_actor?; // observes everything
How it compares
| Maiko | Actix/Ractor | Kafka | |
|---|---|---|---|
| Routing | Topic-based pub/sub | Direct addressing | Topic-based pub/sub |
| Coupling | Loose (actors don't know each other) | Tight (need actor addresses) | Loose |
| Communication | Events | Request-response | Events |
| Scope | In-process | In-process | Distributed |
Where it fits
Event-centric systems: processing stock ticks, device signals, game events, telemetry pipelines.
Not ideal for request-response APIs or RPC patterns.
Quick Start
use *;
;
async
Examples
See the examples/ directory:
pingpong.rs- Event exchange between actorsguesser.rs- Multi-actor game with topics and timingmonitoring.rs- Observing event flow
Core Concepts
| Concept | Description |
|---|---|
| Event | Messages that flow through the system (#[derive(Event)]) |
| Topic | Routes events to interested actors |
| Actor | Processes events via handle_event() and produces events via step() |
| Context | Provides actors with send(), stop(), and metadata access |
| Supervisor | Manages actor lifecycles and the runtime |
| Envelope | Wraps events with metadata (sender, correlation ID) |
For detailed documentation, see Core Concepts.
Test Harness
Maiko includes a test harness (built on the monitoring API) for observing and asserting on event flow:
async
Enable with features = ["test-harness"]. See Test Harness Documentation for details.
Monitoring
The monitoring API provides hooks into the event lifecycle - useful for debugging, metrics, and logging:
use Monitor;
;
let handle = sup.monitors.add.await;
Enable with features = ["monitoring"]. See Monitoring Documentation for details.
Documentation
- Core Concepts - Events, Topics, Actors, Context, Supervisor
- Monitoring - Event lifecycle hooks, metrics collection
- Test Harness - Recording, spies, queries, assertions
- Advanced Topics - Error handling, configuration, design philosophy
- FAQ - Common questions answered
- API Reference - Complete API documentation
Roadmap
Near-term:
- Dynamic actor spawning/removal at runtime
- Improved supervision and error handling strategies
Future:
maiko-actorscrate with reusable actors (IPC bridges, WebSocket, OpenTelemetry)- Cross-process communication via bridge actors
Used In
Maiko powers the daemon in Charon - a USB keyboard pass-through device built on Raspberry Pi. The daemon uses Maiko actors to read input from multiple keyboards, map and translate key events, output USB HID to the host, and coordinate telemetry, IPC, and power management.
Current State
Maiko is battle-tested in the Charon project, where it runs continuously, but it's not yet production-grade. I'd describe it as solid for happy-path scenarios and insufficient for rainy days. Supervision is minimal, backpressure isn't handled, and improved error handling and recovery strategies are planned for 0.3.0.
For now, Maiko demonstrates what it wants to be. That's the state I wanted to reach before sharing it with a wider audience. Want to help shape what comes next? See below.
Contributing
Contributions welcome! Whether it's a bug report, feature idea, or pull request - all input is appreciated.
- Try it out and let us know what you think
- Report issues via GitHub Issues
- Looking to contribute code? Check out good first issues
Acknowledgments
Inspired by Kafka (topic-based routing) and built on Tokio (async runtime).
License
Licensed under the MIT License.