Skip to main content
This page is the guide — the shapes and when to use them. The complete field-level contract lives in the accumulation reference.
These steps handle work that spans more than one event or more than one item. They run in the handler pipeline before the writes, and most handlers use none of them.

accumulate: wait for several events

accumulate gathers arrivals for one entity and fires only when a completion condition is met. The expected count is read from entity state through expected_from:
accumulated is the list of arrivals collected so far, readable in on_complete conditions. Until completion, the handler records the arrival and stops. One thing to watch: dedup_by defaults to the sender, which silently collapses several items from one sender into one; set it to the distinguishing payload field. That default and the materialize_from projection are covered in Accumulation and projection.

compute: aggregate into one value

compute runs a built-in aggregation and stores the result on the entity (store_as names an entity field):
This averages the per-dimension scores into entity.composite, weighting quality/speed/cost at 60% and innovation/scalability at 40%.

filter, reduce, count: process a list

These operate on a list (an entity field or a payload list) and store a result. Their conditions reference each element as item:

fan_out: one event per item

fan_out emits one event per item in a list. Each emitted payload is built with fields, where item is the current element. fan_out.count is how many events were dispatched:
fan_out.count is only available to data_accumulation in the same handler.
The example above records a count for reporting — do not use a count as a completion barrier. Don’t hand-roll a counter with accumulate and expected_count comparisons — that pattern has no dedup and no timeout, and it deadlocks if the last result arrives before the count is written. The platform has a purpose-built barrier for this — a fan-in pin feeding a join: row, which handles dedup, membership, and timeout for you. See examples/routing/fan-in/barrier for the canonical shape. accumulate remains right for aggregations that are not completion barriers.

query: read across entities

query pre-fetches data from other entities, for reports or cross-entity decisions:
count: true here asks the query to return counts — not the count step above. A query can also filter, select specific fields, and store_as a named result; see Handler fields for the full option list.