Expand description
§Ousia
οὐσία — Ancient Greek for “essence” or “substance”.
Ousia is a Postgres-native ORM for Rust that ships with a built-in double-entry ledger as a first-class primitive. It is designed for applications where data, relationships, and money all need to move together — atomically, correctly, and without ceremony.
§What’s inside
§Graph-relational ORM
Model your domain as entities connected by typed edges. Relations are not just foreign keys — they are traversable, queryable graph connections backed by Postgres.
§Double-entry ledger
Every monetary operation — mint, burn, transfer, reserve — is a double-entry transaction. Nothing is deleted. Everything is auditable. The ledger is ACID-safe and lives in the same Postgres connection as your application data.
Money::atomic(&ctx, |tx| async move {
// Lock $60 from user, mint $60 to merchant atomically.
let money = tx.money("USD", user, 60_00).await?;
let slice = money.slice(60_00)?;
slice.transfer_to(merchant, "payment".to_string()).await?;
Ok(())
})
.await?;§Smart fragmentation
Balances are stored as value objects — discrete fragments of value.
The fragmentation engine uses your asset’s natural denomination as a
soft preferred chunk size, with a hard fragment cap (max_fragments)
that automatically scales chunk size up when needed. Every spend is a
consolidation opportunity: change is minted back into at most
burned_count fragments, so active accounts stay lean over time
without any background compaction job.
§FIFO aging
Value objects are selected oldest-first on every spend. Burned rows naturally age to the back of the live index and become eligible for cold-storage archival, keeping your hot dataset small.
§Atomic money operations
The Money API enforces correct usage at the type level:
- Mint — create value out of thin air (deposits, issuance)
- Burn — destroy value permanently (fees, redemptions)
- Transfer — move value between owners atomically
- Reserve — escrow value for a future authority
- Slice — partition a money handle before spending
Unconsumed slices, over-slicing, and double-spend are all caught before hitting the database.
§Quick start
use ousia::{Engine, adapters::postgres::PostgresAdapter};
let adapter = PostgresAdapter::from_pool(pool);
adapter.init_schema().await?;
let engine = Engine::new(Box::new(adapter));
let ctx = engine.ledger_ctx();§v2 highlights
- MessagePack
datacolumn. Object/edge bodies are stored asBYTEAmsgpack instead of JSONB.index_metastays as JSONB so Postgres can GIN-index it. - Renamed tables.
edges → object_edges,unique_constraints → object_constraints. - Partitioned schema.
objects,object_edges,object_constraints, andobject_geoare all partitionedBY LIST (type), one partition per derived type. - FK cascade. Each constraint/geo/edge partition foreign-keys
into the matching
objects_<type>(id)partition withON DELETE CASCADE— no more orphaned children, no more round-trips to clean them up. - Edges declare their endpoints.
#[ousia(from = User, to = Post)]now required onOusiaEdgederives; the trait exposesFROM_TYPE/TO_TYPEandinit_schemauses them to wire the correct FKs. - Compile-time manifest. Every
OusiaObject/OusiaEdgederive pushes into theMANIFESTdistributed slice vialinkme.init_schema()walks the slice — no more enumerating types by hand — and emits atarget/ousia.jsonartifact for tooling. - Composed schema hash. One blake3 hash over every type’s
indexed fields, stored as
major.minor:hashinousia_meta. Major bump → hard error; minor drift → warn and overwrite. - Explicit ledger asset list.
init_ledger_schema(&["USD",…])takes the asset codes from the caller; the library reads no env.
§Feature flags
| Flag | Default | Description |
|---|---|---|
derive | ✓ | Re-export OusiaObject / OusiaEdge derives |
postgres | ✓ | PostgreSQL adapter via sqlx |
ledger | ✓ | Built-in double-entry ledger |
§Ousia
Ousia (οὐσία) is Aristotle’s term for the fundamental substance of a thing — what it is at its core. The name reflects the library’s ambition: to be the essential data substrate of a Rust application, handling entities, relationships, and money in one coherent layer.
Re-exports§
pub use manifest::ManifestKind;pub use manifest::TypeManifestEntry;pub use manifest::MANIFEST;pub use crate::adapters::Adapter;pub use crate::adapters::EdgeRecord;pub use crate::adapters::MultiEdgeContext;pub use crate::adapters::MultiOwnedContext;pub use crate::adapters::MultiPreloadContext;pub use crate::adapters::ObjectRecord;pub use crate::adapters::Query;pub use crate::adapters::QueryContext;pub use crate::edge::query::EdgeQuery;pub use crate::error::Error;pub use query::IndexQuery;pub use ledger;pub use crate::edge::meta::*;pub use crate::edge::traits::*;pub use crate::object::*;
Modules§
- adapters
- edge
- error
- manifest
- Type manifest — compile-time registry of every
ObjectandEdgelinked into the binary. - object
- query
Macros§
Structs§
- Engine
- The Engine is the primary interface for interacting with domain objects and edges. It abstracts away storage details and provides a type-safe API.
- Ousia
- Replica
Config