Event-Condition-Action (ECA)

ECA is a paradigm for specifying reactive behaviour: when an event occurs, check a condition, and if it holds, execute an action. It’s the backbone of active databases, rule engines, complex event processing, and many automation systems.
Author

Benedict Thekkel

Structure

ON   <event>
IF   <condition>
DO   <action>
Part Role Examples
Event Trigger — something that happened INSERT on a table, message arrival, time elapsed, sensor reading
Condition Guard — predicate evaluated at trigger time price > 100, user.role == 'admin', stock < reorder_point
Action Effect — what to do if condition holds Send email, update a row, fire another event, call an API

Origins: Active Databases

ECA was formalised in the active database research of the late 1980s–90s. The canonical expression is the database trigger, still the most widely deployed form:

CREATE TRIGGER reorder_stock
AFTER UPDATE ON inventory
FOR EACH ROW
WHEN (NEW.quantity < 10)
  CALL place_reorder(NEW.product_id);

Key research systems: HiPAC, Ariel, Starburst, POSTGRES (Stonebraker), and later ODE.


Event Types

Primitive events - Data manipulation: INSERT / UPDATE / DELETE on a relation - Temporal: absolute (AT '2026-01-01'), relative (AFTER 5 MINUTES), periodic (EVERY 1 HOUR) - External: message received, HTTP request, hardware signal

Composite events (event algebras) - E1 AND E2 — both occurred (within a window) - E1 OR E2 — either occurred - E1 SEQ E2 — E1 followed by E2 - NOT E — E did not occur within a window - E[n] — E occurred n times


Condition Evaluation

Conditions are predicates over: - the event parameters (old/new values in DB triggers) - database/system state at evaluation time - derived context (aggregates, joins, external lookups)

Timing matters — when is the condition checked relative to the event?

Timing Description
Immediate Checked synchronously during the triggering transaction
Deferred Checked at transaction commit
Decoupled Checked in a separate async transaction

Action Semantics

Actions can be: - DML operations (INSERT, UPDATE, DELETE) - Procedure/function calls - Message/notification dispatch - Further event emission (enabling rule chaining)

Coupling modes describe how the action relates to the triggering transaction:

Mode Meaning
Immediate Runs inside the same transaction
Deferred Runs at end of triggering transaction
Decoupled Runs in a new, independent transaction

Rule Chaining & Termination

Because an action can trigger another rule, chains and cycles are possible:

R1: ON insert(A) → insert(B)
R2: ON insert(B) → insert(C)
R3: ON insert(C) → insert(A)   ← cycle

Termination analysis is a core ECA problem. Approaches: - Static analysis of trigger dependency graphs - Cycle detection (necessary but not sufficient — cycles don’t always diverge) - Depth limits / recursion guards at runtime - Triggering graph — directed graph where R→R’ if R’s action can trigger R’


Conflict Resolution & Priority

When multiple rules fire on the same event, execution order matters. Strategies: - Priority ordering — explicit numeric priority - Specificity — more specific condition wins (as in expert systems) - Recency — most recently added rule fires first - Arbitrary / non-deterministic — system chooses, rules must be independent


Granularity

Level Semantics
Row-level (FOR EACH ROW) Rule fires once per affected tuple
Statement-level (FOR EACH STATEMENT) Rule fires once per DML statement

Row-level gives access to OLD and NEW tuple values; statement-level does not (in most systems).


ECA Beyond Databases

Complex Event Processing (CEP) Systems like Esper, Flink CEP, and AWS EventBridge detect patterns across event streams. The event component becomes a full pattern language over time windows.

Business Rule Engines Drools, CLIPS, Jess implement the Rete algorithm to efficiently match ECA-style production rules over a working memory. Conditions can span multiple facts simultaneously.

Workflow & Automation Zapier, n8n, GitHub Actions — all ECA at a higher abstraction: ON push to main IF tests pass DO deploy.

IoT / SCADA Sensor threshold rules are pure ECA: ON temperature_reading IF value > 80 DO trigger_alarm.

Frontend / Reactive UI Event listeners + guards: ON click IF form.valid DO submit(). React’s useEffect with dependency arrays is a constrained ECA form.


ECA in Practice: SQL Triggers (PostgreSQL)

-- Event: AFTER INSERT on orders
-- Condition: order total > 1000
-- Action: insert into high_value_orders

CREATE OR REPLACE FUNCTION flag_high_value()
RETURNS TRIGGER AS $$
BEGIN
  IF NEW.total > 1000 THEN
    INSERT INTO high_value_orders(order_id, flagged_at)
    VALUES (NEW.id, NOW());
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER check_order_value
AFTER INSERT ON orders
FOR EACH ROW
EXECUTE FUNCTION flag_high_value();

Known Pitfalls

  • Hidden control flow — triggers are invisible to application code, making behaviour hard to trace
  • Performance — row-level triggers on bulk operations can be catastrophic
  • Cascading failures — a bad action can corrupt data across many triggered rules before being caught
  • Testing difficulty — ECA logic is tightly coupled to data state, hard to unit test in isolation
  • Ordering non-determinism — when multiple rules fire, subtle bugs emerge from assumed ordering

Summary

ECA = reactive computation model
    Event   → what happened (primitive or composite)
    Condition → is it relevant right now?
    Action  → what to do about it

Key concerns: coupling mode, granularity, chaining,
              termination, priority, performance

It’s one of the oldest and most pervasive patterns in computing — showing up identically in DB triggers, CEP engines, rule systems, automation platforms, and reactive UI frameworks.

Back to top