0.459 (18 Jun 2026)

18 June, 2026

This release adds conditional subscriber triggers with filter expressions on @on.

Conditional Subscriber Triggers

The @on attribute now accepts an optional third argument: a boolean expression evaluated before an event is published. Events that don't match the filter are dropped before they're published, so the subscriber never runs.

model Order {
    fields {
        status OrderStatus
        total Number
    }
 
    @on([create], processNewOrder, order.status == OrderStatus.New)
    @on([create, update], flagBigOrder, order.total > 1000)
}
// Only fire when status just changed to Shipped
@on([update], onShipped, order.status == OrderStatus.Shipped && previous.status != OrderStatus.Shipped)
 
// Only when the status actually changed
@on([update], trackStatusChange, order.status != previous.status)

The previous keyword gives you access to the row's prior state for update and delete events, enabling transition-based filters. You can also use ctx in filter expressions, just like in permission rules:

@on([create], auditAuthenticated, ctx.isAuthenticated)
@on([delete], guard, ctx.env.STAGE == "production")

Fixes and Improvements

  • Flow step replay fidelity: fixed a bug where nested JSONB keys were incorrectly camelCased on replay, causing first execution and replay to return different values from flow steps.
  • NonRetriableError messages: NonRetriableError now surfaces the original error message instead of wrapping it in a generic "exhausted step retries" message, making flow errors easier to debug.

For any issues or feedback, please contact us at help@keel.so.

Thank you for using Keel!