Pharos RS is a lightweight Rust framework for building domain-driven, CQRS-friendly, event-driven applications.
The public API is intentionally small: a domain core, an application-contract crate, and a convenience facade that reexports the stable surface so users can get started quickly without learning every crate at once.
- Domain modeling primitives:
Entity,AggregateRoot,ValueObject,DomainEvent - Validated value objects via
value_object!; strongly typed UUID v7 IDs viaid_type! Money/Currencyini128minor units — checked arithmetic, lossless allocation, crypto magnitudes (wei) included- Command/query handlers with validation + tracing applied by the
dispatchseam - Repository abstraction with optimistic concurrency control
- Atomic aggregate save + outbox in one transaction (
TransactionalRepository/save_and_enqueue_in) - In-process domain event bus with configurable error policy, retry, and dead-letter decorators
- Integration event envelope with typed correlation/causation, tenant, trace and schema metadata
- Schema evolution through JSON upcasters (
VersionedJsonCodec) - Outbox dispatcher with per-key ordered concurrency and a failed→DLQ sweep
- Idempotent consumers in one call (
process_idempotent) - Durable event sourcing and sagas on PostgreSQL (
PgEventStore,PgSnapshotStore,PgSagaStore) - Saga deadlines: schedule timeouts on
Start/Advanceand sweep them withSagaRunner::run_due_timeouts - Tower as the cross-cutting pipeline seam (timeouts, limits, authorization)
- Observability with
tracingspans andmetricscounters throughout
| Crate | Purpose |
|---|---|
pharos-core |
Domain primitives: entities, aggregates, repositories, value objects, and domain events |
pharos-app |
Application contracts: command/query handlers, event bus, integration events, upcasters |
pharos-messaging |
Broker-facing contracts: messages, publishers/consumers, retry, outbox/inbox, DLQ |
pharos-macros |
Derive macros and id_type! for reducing boilerplate |
pharos |
Convenience facade that reexports the stable API and prelude |
flowchart TD
Domain[Domain Model]
Core[pharos-core]
Macros[pharos-macros]
App[pharos-app]
Example[examples/order]
Domain --> Core
Macros --> Core
App --> Core
Example --> Core
Example --> App
Core --> Entity[Entity]
Core --> Aggregate[AggregateRoot]
Core --> DomainEvent[DomainEvent]
Core --> Repository[Repository]
App --> CQRS[Command and Query Handlers]
App --> Eventing[Event Bus and Handlers]
App --> Outbox[Outbox and Inbox Contracts]
App --> Messaging[Messaging Contracts]
pharos-rs/
├── crates/
│ ├── pharos-core # domain primitives
│ ├── pharos-macros # derive macros + id_type!
│ ├── pharos-messaging # broker contracts, retry, outbox/inbox, DLQ, consumer groups
│ ├── pharos-app # CQRS, EventBus, integration events, upcasters, Tower adapters
│ ├── pharos-memory # in-memory adapters for tests and local development
│ ├── pharos-postgres # pooled PostgreSQL adapters
│ ├── pharos-redis # Redis messaging adapter
│ ├── pharos-axum # Axum extractors/helpers for handlers
│ ├── pharos-saga # saga/process-manager primitives
│ ├── pharos-es # event sourcing primitives
│ ├── pharos-kafka # Kafka + schema registry adapters
│ ├── pharos-nats # NATS messaging adapters
│ ├── pharos-proto # Protobuf binary serialization for integration events
│ ├── pharos-testing # EventCapture and test helpers
│ └── pharos # convenience meta-crate (re-exports + prelude)
├── examples/
│ ├── order
│ ├── multi-tenant
│ └── modular-monolith
└── tools/
└── pharos-init # interactive project scaffolder
pharos-init is an interactive CLI that asks three high-level questions about your system and scaffolds the right project structure automatically — no Docker, Redis, or PostgreSQL knowledge required up front.
cargo install --path tools/pharos-init
pharos-initYou will be asked:
- What kind of system? — single service, modular monolith, event-driven, or high-throughput pipeline
- How does it receive work? — HTTP API or background worker
- Does it need to persist state? — in-memory or durable storage (skipped for event-driven/high-throughput)
From those answers pharos-init derives persistence, event delivery, broker, serialization format, and HTTP layer automatically, and generates a ready-to-build project.
Most applications should start with the pharos facade and import from its prelude:
pharos = { package = "pharos-rs", version = "0.1", features = ["macros"] }use pharos::prelude::*;If you want lower-level control, depend on pharos-core, pharos-app, or pharos-macros directly.
| Feature (crate) | Default | Enables |
|---|---|---|
macros (pharos) |
yes | #[derive(...)] and id_type! (pharos-macros) |
tower (pharos-app) |
no | CommandHandlerService/QueryHandlerService (pipeline seam) |
retry (pharos-app) |
no | Retrying event-handler decorator (Tokio timer) |
tenant-task-local (pharos-app) |
no | CURRENT_TENANT task-local (explicit TenantContext is canonical) |
- Documentation index
- 30-minute tutorial
- Complete usage guide
- Architecture guide — event-driven model, outbox, inbox, patterns
- Crate reference — per-crate API tables
- Production operations
- Observability setup
- Decision matrix
- Cookbook
- Pitfalls
| Example | Shows |
|---|---|
examples/order |
Canonical DDD/CQRS/outbox suite — run with cargo run -p order |
examples/multi-tenant |
TenantContext + per-tenant repositories and row-level isolation — cargo run -p multi-tenant |
examples/modular-monolith |
Two bounded contexts in one process via the in-process event bus — cargo run -p modular-monolith |
# build
cargo build --workspace
# test (requires Docker for container-backed integration tests)
cargo test --workspace --all-features
cargo test-docker # = cargo test --workspace --all-features -- --test-threads=1
# docs
cargo docs # alias for: cargo doc --workspace --no-deps- Explicit rather than magical
- Framework-light
- Idiomatic Rust
- Compatible with DDD and CQRS patterns
- Extensible through traits and adapters
- Useful for modular monoliths and as a foundation for distributed event-driven systems
Pharos RS stands on top of the Rust ecosystem. Thanks to the maintainers and contributors of these third-party libraries used directly across this workspace:
- async-nats
- axum
- chrono
- console
- criterion
- dashmap
- dialoguer
- futures
- garde
- http
- indoc
- metrics
- proc-macro2
- prost
- quote
- rdkafka
- redis
- reqwest
- serde
- serde_json
- sqlx
- syn
- testcontainers
- thiserror
- tokio
- tower
- tracing
- tracing-subscriber
- uuid
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
