Skip to content

EVENT

An Event in DeQL represents an immutable fact — something that has already happened. Events are the fundamental unit of truth in a DeQL system. They are immutable values.

Events serve as:

  • The source of truth — all state is derived exclusively from events (SELECT * from <<AggregateName>>$Events)
  • The output of decisions — decisions emit events as outcomes (EMIT AS SELECT EVENT)
  • The input to aggregates — aggregate state is derived by replaying events (<Aggregate>$Agg)
  • The input to projections — read models derive their views by querying events (<Aggregate>$Events)
CREATE EVENT <Name> (
<field> <TYPE>,
...
);

Use CREATE OR REPLACE to overwrite an existing definition:

CREATE OR REPLACE EVENT <Name> (
<field> <TYPE>,
...
);
CREATE EVENT EmployeeHired (name STRING, grade STRING);
CREATE EVENT EmployeePromoted (new_grade STRING);
CREATE EVENT AccountOpened (initial_balance DECIMAL(12,2));
CREATE EVENT Deposited (amount DECIMAL(12,2));
CREATE EVENT ItemAdded (
sku STRING,
quantity INT,
price DECIMAL(10,2)
);
CREATE EVENT CartCheckedOut (
total_amount DECIMAL(12,2)
);
CREATE EVENT ItemRemoved (
sku STRING
);

Events are produced inside decisions using the EMIT AS SELECT EVENT clause. Field assignment uses the := operator:

CREATE DECISION DepositFunds
FOR BankAccount
ON COMMAND Deposit
STATE AS
SELECT initial_balance AS balance
FROM DeReg."BankAccount$Agg"
WHERE aggregate_id = :account_id
EMIT AS
SELECT EVENT Deposited (
amount := :amount
)
WHERE balance >= :amount;

The :amount comes from the command, and balance comes from the STATE AS query.

Events are queried using the $Events suffix under the DeReg schema with quoted identifiers. The stream_id column identifies which aggregate instance the event belongs to:

-- Query raw events
SELECT stream_id, event_type, seq, data
FROM DeReg."BankAccount$Events"
ORDER BY stream_id, seq;
-- Use in projections (stream_id for grouping)
CREATE PROJECTION AccountBalance AS
SELECT
stream_id AS aggregate_id,
LAST(data.initial_balance) AS balance
FROM DeReg."BankAccount$Events"
GROUP BY stream_id;

The data. prefix accesses the event’s payload fields.

Every event automatically carries metadata beyond its declared fields:

FieldDescription
stream_idThe aggregate instance this event belongs to
event_typeThe name of the event (e.g., 'Deposited')
data.*The declared payload fields
seqPosition in the aggregate’s event stream
timestampWhen the event was recorded
PropertyDescription
ImmutableOnce emitted, an event never changes
OrderedEvents within a stream have a defined sequence
Self-describingEach event carries its type and payload
ReplayableAny state can be rebuilt by replaying events
QueryableAccessed via DeReg."<Name>$Events" in projections