SklilJ
skilj is a Rust library for building event-sourced applications backed by Postgres. You define
your domain as events (facts that happened) and commands (requests to make something
happen), and skilj handles storage, consistency checking, and exposing it all over GraphQL and
REST — so you can focus on the domain logic itself.
Why not classic aggregates?
Most event-sourced libraries make you pick one fixed "aggregate" boundary up front (an Account,
an Order) and every command for that aggregate replays its entire history. skilj uses a
Dynamic Consistency Boundary (DCB) instead: events and commands carry tags (e.g. wallet: "w1"), and a command's consistency check spans exactly the tagged events it needs — no more, no
less. A command that touches two things at once (say, enrolling a student in a course) can check
both their histories in one atomic decision, without either one having to "own" the other.
A quick look
This is trimmed from templates/skilj-template/src/wallet.rs
— see that file for the complete, running version:
// An event: something that happened, tagged by which wallet it belongs to.
;
// A command: a request, decided against only the events sharing its tags -
// here, every Deposited/Withdrawn event for this one wallet, nothing else.
;
That's it — no separate storage layer to wire up, no aggregate repository to implement. Add a
Projection (also shown in wallet.rs) when you need a read-optimised view instead of replaying
events on every query.
Getting started
The fastest way to try it is to generate a small, working project:
That gives you a runnable server with one bounded context (the wallet example above) already wired up — see its own README for how to run it against Postgres.
To add skilj to an existing project instead:
[]
= "0.0"
skilj-demo in this repository is a larger worked example (two bounded contexts:
banking and courses) if you want to see more before committing.
Crates in this workspace
| Crate | What it is |
|---|---|
skilj |
The main library - start here. A thin facade over skilj-core/skilj-graphql/skilj-rest. |
skilj-core |
The domain engine: events, commands, projections, and persistence. No web framework dependency. |
skilj-graphql |
The GraphQL surface - usable on its own if you don't need REST. |
skilj-rest |
The REST surface - authenticated routes for agents and automated callers. |
skilj-codegen |
Optional: generate event/command boilerplate from a declarative .skilj.toml file instead of hand-writing it. |
skilj-tui |
cargo install skilj-tui - a terminal console (GraphQL client) for browsing and operating a running deployment. |
skilj-inspector |
cargo install skilj-inspector - a terminal console that reads straight from Postgres, for when the GraphQL server isn't running. |
skilj-macros |
Internal proc-macros, re-exported through skilj-core/skilj (not uniformly - each macro picks whichever crate it applies to) - you won't normally add this directly. |
Documentation
specs/skilj.allium- the behavioural specification: what the system guarantees, independent of the Rust code.docs/architecture.md- how that's actually built in Rust, including the reasoning behind each design decision. It's written as a running design log, so later sections assume you've read the earlier ones.docs/rest-event-reading.md- the three ways to consume the REST event stream and when to use each.
Contributing
Bug reports and pull requests are welcome - see CONTRIBUTING.md for how to
build, test, and submit changes, and CODE_OF_CONDUCT.md for community
expectations. Found a security issue? See SECURITY.md instead of opening a
public issue.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.