Skip to main content

Project layout

A Riverbase application keeps domain logic and process wiring in separate crates. The domain crate knows nothing about HTTP binding, ports, or config files. The service crate is a thin binary that loads configuration, builds a runtime, and mounts domains.

my-app/
├── Cargo.toml # workspace: members + [workspace.dependencies]
├── domain/ # todo-domain: the bounded context
│ ├── Cargo.toml
│ ├── migrations/ # Diesel migrations for this domain's tables
│ └── src/
│ ├── lib.rs # re-exports
│ ├── domain.rs # domain! — namespace, engine slots, spawn
│ ├── command.rs # command_engine! — payloads, handlers, typed helpers
│ ├── aggregate.rs # TodoAggregate — #[domain_action] methods
│ ├── query.rs # query_resource!, report_resource!, query_engine!
│ ├── service.rs # optional service engine (non-CQRS capabilities)
│ └── postgres/
│ ├── schema.rs # diesel table! with shared domain fields
│ ├── entity.rs # domain_row! + pg_domain_entity!
│ ├── migrate.rs # embedded migrations
│ └── mod.rs # DomainStoreSpec for the domain
└── service/ # todo-service: the binary
├── Cargo.toml
├── riverbase.toml # service defaults (env vars override)
└── src/main.rs # RiverbaseApp::init → DomainRuntime → spawn → mount → serve

This is the layout the Tutorial builds. The Quick start keeps the same files in one crate, which is fine while there is one domain. A split deployment adds one more binary crate (split/) that mounts the same domain as two processes. See Deployment.

Start a new domain​

Copy the quick start's files into a new domain crate and rename the resource. Every domain needs the same six pieces: a query resource, a command engine, an aggregate, a Diesel entity with its migration, a store spec, and the domain! declaration.

Replace the starter policy

The quick start declares policy: public(...) because it has no tenants. Replace it with a real row policy before production. See Multi-tenancy.

Dependency direction​

Keep it one-way:

  • The domain crate depends on riverbase_core and riverbase_proc. Gate anything that needs axum (RxDB collections, Casbin helpers) behind an optional http feature, as todo-domain does.
  • The service crate depends on riverbase_http and the domain crates it mounts.
  • Domains never depend on each other's crates. Cross-domain calls go through the command invoker or integration messages. See Domains and namespacing.

Next: Configuration.