Core capabilities
- Flexible JSON payloads – events accept arbitrary JSON; scalars normalize into strings for consistent state tracking, while nested objects remain queryable through filters like
payload.status = "active". - Immutable data structure – once persisted, events cannot be edited or deleted. You can archive aggregates or shift them into long-term storage, but history stays intact for audits and compliance.
- Event sourcing and replay – replay stored events through plugins with
dbx plugin replay <plugin> <aggregate>to rebuild read models or inspect historical state. Updates are expressed as events rather than in-place writes. - Merkle tree integration – every aggregate maintains a Merkle tree of its events so
dbx aggregate verifycan detect tampering by recomputing the root hash. - Built-in audit trails – administrators can issue scoped tokens for auditors, granting read-only access to selected aggregates and their events.
- Extensible read models – plugins consume the job queue and can request only the slices they need (event payload, materialized state, schema, or combinations). This keeps the write path isolated from read-model concerns.
- Domain sharding – create multiple domains to hard-segregate data; each shard keeps its own Merkle tree, quotas, and replication targets so tenants cannot bleed into each other’s history.
- Remote replication –
dbx push,dbx pull, anddbx watchkeep domains in sync with Merkle + version checks. Divergent histories abort automatically instead of rewriting events. - Observability and security – Prometheus metrics cover HTTP traffic and plugin queue health, while Ed25519-signed tokens plus optional payload encryption protect access.
Restriction modes
EventDBX enforces schemas based on the restriction mode you choose at startup (dbx start --restrict=<mode>):
Switch modes without migrating data; just restart the daemon with the desired flag.
Column definitions
Schemas are powered by acolumn_types map that defines both storage type and validation rules.
Rules you can layer on a column:
required– field must be present on every event payload.contains/does_not_contain– substring checks fortext.regex– one or more patterns fortext.format– built-in validators such asemail,url,credit_card,camel_case,snake_case,pascal_case,upper_case_snake_case,country_code,iso_8601, andwgs_84.length–{ "min": <usize>, "max": <usize> }fortextor decodedbinarypayloads.range–{ "min": <value>, "max": <value> }for numeric or temporal types.properties– nestedcolumn_typesforobjectfields, letting you keep applying the same rule set recursively.
Aggregate operation costs
Most commands boil down to a handful of RocksDB reads/writes. Use the table below when planning workloads or sizing clusters:
Staged events live in
.eventdbx/staged_events.json. Queue them with aggregate apply --stage, preview with aggregate list --stage, and flush the entire batch via aggregate commit for all-or-nothing persistence.