Skip to main content

Event

Events provide a publish-subscribe mechanism for decoupling business logic in FlowOn Logic. Instead of directly calling flows from other flows or creating tight dependencies between components, you can publish an event and let interested handlers respond to it. This creates a flexible, loosely-coupled architecture where publishers don't need to know about subscribers.

The Challenge: Tightly Coupled Logic

As business logic grows, components often become tightly intertwined. A flow that processes an order might directly call:

  • A flow to send confirmation emails
  • A flow to update inventory
  • A flow to notify the warehouse
  • A flow to sync with the ERP system
  • A flow to update analytics

This creates several problems:

  1. Rigid Dependencies: The order flow must know about all downstream processes
  2. Difficult Changes: Adding a new action (like loyalty points) requires modifying the order flow
  3. Testing Complexity: You can't test the order flow without triggering all downstream effects
  4. Performance Impact: Synchronous calls to multiple flows slow down the main process
  5. Single Point of Failure: If one downstream flow fails, the entire chain may fail

The Solution: Event-Driven Architecture

Events introduce a publish-subscribe pattern that decouples publishers from subscribers:

  1. Publishers announce that something happened (e.g., "an order was placed")
  2. Subscribers independently listen for events they care about and react accordingly
  3. Publishers don't know who is listening or what actions will be taken
  4. Subscribers don't know who published the event or why

This decoupling allows you to add, remove, or modify subscribers without changing the publisher.

Event System Components

The FlowOn Logic event system consists of three components:

ComponentPurposeCreated By
Event DefinitionDefines the event structure (name and properties)Developer at design time
Event HandlerSubscribes to an event and specifies how to respondDeveloper at design time
Event InstanceThe actual event occurrence with dataSystem at runtime (via Publish Event step)

Event Definition

An Event Definition declares that a particular type of event exists in your system. It defines what data (properties) the event carries. Think of it as a contract: anyone publishing this event must provide these properties, and any handler can expect to receive them.

Structure

PropertyRequiredDescription
NameYesUnique identifier for the event (e.g., "OrderPlaced", "CustomerCreated")
ProjectYesThe FlowOn Project this event belongs to
DescriptionNoDocumentation explaining when this event is published
PropertiesYesList of data properties the event carries

Event Properties

Properties are like inputs—they define what data accompanies the event:

Property AttributeDescription
NameUnique identifier for the property
TypeData type (String, Integer, Money, Entity Reference, etc.)
RequiredWhether the property must be provided when publishing
DescriptionDocumentation explaining what the property represents

Example: Order Placed Event Definition

Event Definition: OrderPlaced
Project: E-Commerce
Description: "Published when a new order is successfully created"

Properties:
┌─────────────────────┬──────────────────┬──────────┬────────────────────────┐
│ Property Name │ Type │ Required │ Description │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ OrderId │ Entity Reference │ Yes │ Reference to the Order │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ CustomerId │ Entity Reference │ Yes │ Reference to Customer │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ OrderNumber │ String │ Yes │ Human-readable order # │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ TotalAmount │ Money │ Yes │ Order total value │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ OrderDate │ DateTime │ Yes │ When order was placed │
├─────────────────────┼──────────────────┼──────────┼────────────────────────┤
│ IsFirstOrder │ Boolean │ No │ Is this customer's │
│ │ │ │ first order? │
└─────────────────────┴──────────────────┴──────────┴────────────────────────┘

Event Handler

An Event Handler subscribes to an Event Definition and specifies what happens when that event is published. It connects the event to a Logic Flow that contains the actual business logic to execute.

Structure

PropertyRequiredDescription
NameYesUnique identifier for the handler
ProjectYesThe FlowOn Project this handler belongs to
Event DefinitionYesThe event this handler subscribes to
Logic FlowYesThe flow to execute when the event is published
Execution ModeYesSynchronous or Asynchronous
Input BindingsYesMapping between event properties and flow inputs

Execution Mode

ModeBehaviorUse When
SynchronousPublisher waits for handler to complete; handler runs in same transactionHandler must complete before publisher continues; data integrity required
AsynchronousPublisher continues immediately; handler runs in backgroundNon-critical processing; long-running operations; external integrations

Input Bindings

Input bindings map event properties to flow inputs. When the event is published, the handler passes the event data to the flow using these bindings.

Event Property → Flow Input
─────────────────────────────
OrderId → OrderReference
CustomerId → CustomerReference
TotalAmount → Amount
OrderDate → PlacedOn

Example: Send Order Confirmation Handler

Event Handler: SendOrderConfirmation
Project: E-Commerce
Event Definition: OrderPlaced
Logic Flow: SendOrderConfirmationEmail
Execution Mode: Asynchronous

Input Bindings:
┌─────────────────────┬─────────────────────┬─────────────────────────────┐
│ Event Property │ Flow Input │ Description │
├─────────────────────┼─────────────────────┼─────────────────────────────┤
│ OrderId │ OrderReference │ Order to include in email │
├─────────────────────┼─────────────────────┼─────────────────────────────┤
│ CustomerId │ CustomerReference │ Customer to send email to │
├─────────────────────┼─────────────────────┼─────────────────────────────┤
│ OrderNumber │ OrderNum │ For email subject line │
├─────────────────────┼─────────────────────┼─────────────────────────────┤
│ TotalAmount │ OrderTotal │ For email body │
└─────────────────────┴─────────────────────┴─────────────────────────────┘

Multiple Handlers for One Event

A single Event Definition can have multiple handlers. When the event is published, all registered handlers are triggered:

Event: OrderPlaced

├──► Handler: SendOrderConfirmation (Async)
│ └──► Flow: SendOrderConfirmationEmail

├──► Handler: DeductInventoryOnOrder (Sync)
│ └──► Flow: DeductOrderInventory

├──► Handler: NotifyWarehouse (Async)
│ └──► Flow: SendWarehouseNotification

├──► Handler: UpdateAnalytics (Async)
│ └──► Flow: RecordOrderAnalytics

└──► Handler: AwardLoyaltyPoints (Async)
└──► Flow: CalculateAndAwardPoints

Event Instance

An Event Instance is created at runtime when the Publish Event step executes in a Logic Flow. It represents a specific occurrence of the event with actual data values.

Characteristics

CharacteristicDescription
ImmutableOnce created, the event instance cannot be modified
Read-OnlyHandlers can read event data but cannot change it
TimestampedSystem records when the event was published
TraceableEvent instances can be tracked for auditing and debugging

Event Lifecycle

┌─────────────────────────────────────────────────────────────────────┐
│ EVENT INSTANCE LIFECYCLE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. PUBLISH │
│ └── Flow executes "Publish Event" step │
│ └── Provides values for event properties │
│ │
│ 2. CREATE │
│ └── System creates immutable Event Instance │
│ └── Instance contains snapshot of provided data │
│ │
│ 3. DISPATCH │
│ └── System identifies all registered handlers │
│ └── Synchronous handlers execute first (in order) │
│ └── Asynchronous handlers queued for background execution │
│ │
│ 4. HANDLE │
│ └── Each handler's flow executes │
│ └── Event data passed via input bindings │
│ └── Flow performs its business logic │
│ │
│ 5. COMPLETE │
│ └── All handlers have executed (or been queued) │
│ └── Publisher flow continues (if sync handlers done) │
│ │
└─────────────────────────────────────────────────────────────────────┘

Publishing Events

Events are published using the Publish Event step in a Logic Flow:

Publish Event Step

ParameterDescription
Event DefinitionThe event type to publish
Event Properties BindingValues to assign to each event property

Example: Publishing OrderPlaced Event

Flow: CreateOrder

Steps:
1. [Validation] - Validate order data
2. [Save Entity] - Save the Order record
3. [Loop] - For each line item
└── [Save Entity] - Save Order Line record
4. [Publish Event] ◄── PUBLISH EVENT
- Event Definition: OrderPlaced
- Property Bindings:
- OrderId: Order.Id
- CustomerId: Order.CustomerId
- OrderNumber: Order.OrderNumber
- TotalAmount: Order.TotalAmount
- OrderDate: Now()
- IsFirstOrder: CustomerOrderCount = 1
5. [Set Output] - Return Order ID

When step 4 executes:

  1. An immutable Event Instance is created with the bound values
  2. All synchronous handlers execute (e.g., DeductInventoryOnOrder)
  3. Asynchronous handlers are queued (e.g., SendOrderConfirmation)
  4. The flow continues to step 5

Best Practices

Design Events Around Business Moments: Events should represent meaningful business occurrences ("OrderPlaced", "PaymentReceived", "CustomerUpgraded") not technical operations ("RecordSaved", "FieldUpdated").

Include Sufficient Context: Event properties should contain enough information for handlers to do their work without querying for additional data. Include IDs, key values, and relevant context.

Keep Events Focused: Each event should represent one thing that happened. Don't create "OrderPlacedAndPaymentProcessed"—create two separate events.

Use Sync Handlers Sparingly: Synchronous handlers block the publisher. Reserve them for operations that must complete before the publisher continues (e.g., inventory deduction before order confirmation).

Design for Handler Failure: Asynchronous handlers can fail independently. Design handlers to be idempotent (safe to retry) and implement error handling.

Document Event Contracts: Clearly document when each event is published, what properties it contains, and what handlers should expect.

Avoid Circular Events: Be careful not to create event chains where Handler A publishes an event that triggers Handler B, which publishes an event that triggers Handler A.

Version Events Carefully: If you need to change an event's properties, consider creating a new event version rather than modifying existing handlers.

Use Meaningful Names: Event names should be past tense and describe what happened: "OrderPlaced" not "PlaceOrder", "CustomerCreated" not "CreateCustomer".

Consider Event Ordering: When multiple handlers exist, synchronous handlers run first (in registration order), then asynchronous handlers are queued. Design accordingly.