← Back to Documentation

Event-Driven Architecture

ARO uses direct event dispatch to connect feature sets. No complex pub/sub patterns, no subscriptions, no event streams. Just emit an event to a feature set by name.

The ARO Philosophy

Events should be simple. Emit to a feature set name, receive in the <event> variable. That's it. No configuration, no subscription management, no event bus complexity.

Event Emission

Use the <Emit> action to dispatch events to other feature sets. The target is simply the feature set name.

(* Creating a user and emitting events *)
(Create User: Registration) {
    <Extract> the <data> from the <request: body>.
    <Create> the <user: User> with <data>.
    <Store> the <user> in the <user-repository>.

    (* Emit to a specific feature set by name *)
    <Emit> to <Send Welcome Email> with {
        email: <user: email>,
        name: <user: name>
    }.

    <Return> a <Created: status> with <user>.
}

Receiving Events

Feature sets receive events in the <event> variable. Access fields using the familiar qualifier syntax.

(Send Welcome Email: Notifications) {
    <Extract> the <email> from the <event: email>.
    <Extract> the <name> from the <event: name>.

    <Send> the <welcome-email> to the <email> with {
        subject: "Welcome!",
        body: "Hello ${<name>}, welcome to our service!"
    }.

    <Return> an <OK: status> for the <notification>.
}

Multiple Event Handlers

A single action can emit to multiple feature sets, enabling clean separation of concerns. Each handler runs independently.

(createOrder: E-Commerce) {
    <Extract> the <userId> from the <request: body>.
    <Extract> the <items> from the <request: body>.

    <Create> the <order: Order> with {
        id: <generated-id>,
        userId: <userId>,
        items: <items>,
        status: "placed"
    }.

    <Store> the <order> in the <order-repository>.

    (* Dispatch events to multiple handlers *)
    <Emit> to <Send Order Confirmation> with <order>.
    <Emit> to <Update Inventory> with { items: <items> }.
    <Emit> to <Track Revenue> with { amount: <order: total> }.

    <Return> a <Created: status> with <order>.
}

Event Handlers

Each handler is a standard feature set that receives the event data:

(Send Order Confirmation: Notifications) {
    <Extract> the <orderId> from the <event: id>.
    <Extract> the <userEmail> from the <event: userEmail>.

    <Send> the <email> to the <userEmail> with {
        subject: "Order Confirmed",
        body: "Your order ${<orderId>} has been placed."
    }.

    <Return> an <OK: status> for the <confirmation>.
}

(Update Inventory: Inventory Management) {
    <Extract> the <items> from the <event: items>.

    for each <item> in <items> {
        <Decrement> the <stock> for the <item: productId>.
    }

    <Return> an <OK: status> for the <inventory>.
}

(Track Revenue: Analytics) {
    <Extract> the <amount> from the <event: amount>.
    <Increment> the <daily-revenue> by <amount>.
    <Return> an <OK: status> for the <analytics>.
}

Why This Approach?

Simplicity

No event bus configuration. No subscription management. No event type hierarchies. Just emit to a name, receive in <event>.

Clarity

The target feature set is explicit in the code. You can see exactly where events go without tracing through configuration files.

Decoupling

Event emitters don't need to know how handlers are implemented. Handlers can be added, removed, or modified independently.

Learn More

See the full event dispatch specification in ARO-0012: Simple Event Dispatch.