A rule engine and trigger framework

Match product events against versioned rules and run actions safely: rule shape, evaluation, idempotent actions, rate limits, testing and audit.

On the roadmap:Staff Engineer · step 4: Real-time at scale

Lesson 4 of 6 · 11 min read · quiz · exercise

What it is

A rule engine (or trigger framework) lets you say "when this happens and if these conditions hold, do that", without writing a new code path each time. Examples: send a welcome message when a user signs up, flag an order when the amount is unusual, award a badge after five purchases.

Product and operations teams want to change these often, so the rules should be data that a service evaluates, not code that must be redeployed.

Figure SDA-SQR-04-1 · From event to action · © forcsguy.com

What a rule contains

  • Identity and version: id, version, owner, enabled. Never edit in place; publish a new version so you can audit and roll back.
  • Trigger: an event type, or a schedule for time-based rules.
  • Condition: a structured tree such as all of [ plan = free, country in (IN, US), purchases >= 5 ], or a restricted expression language. Avoid arbitrary code.
  • Action: a named action with parameters (send_email(template_id), add_badge(name)).
  • Controls: cooldown, per-user and global limits, start and end dates.

Evaluating efficiently

  • Index rules by event type so an event only looks at its few candidate rules, not all rules.
  • Fetch extra user data (attributes, counters) lazily and cache it for the duration of the event, as lookups usually cost more than the comparisons.
  • For time-based conditions ("14 days without login") run a scheduled scan or use delayed events, rather than polling every user.
  • Evaluate in workers that are partitioned by user, so state like cooldowns and counters for one user is handled in order.

Safe, idempotent actions

Events can be delivered more than once and workers retry. Guard every action with an idempotency key, for example rule:version:user:window, stored in a unique-key table or key-value store before (or together with) performing the action.

Figure SDA-SQR-04-2 · Idempotent action execution · © forcsguy.com

Operating a rule engine

  • Validation at publish time: reject unknown fields, huge conditions and loops.
  • Dry run and replay: run a new rule against recent historical events and report how many it would fire, before enabling it.
  • Kill switch per rule and globally, since a bad rule can email a million users.
  • Limits: maximum rule size, evaluation time and actions per event.
  • Audit: who changed which version and when; for each event, which rules fired or were skipped and why.
  • Know the cost: a large pile of rules becomes software nobody understands. Fowler's advice is to prefer plain code for logic that rarely changes, and use rules for what truly varies.

Real-world reading

Check your understanding

Question 1 of 3

0 correct so far

Why should rules be data rather than code deployed with the app?

Go deeper

  • Rules engine by Martin Fowler: a balanced view on when engines help
  • Drools documentation by Drools community: a mature open-source rules engine
  • Enterprise Integration Patterns by Hohpe and Woolf: idempotent receiver and message router patterns

© 2026 forcsguy.com. Original lesson text and diagrams. Books and sites linked above belong to their authors.