Low Level Design: Rule Engine

What Is a Rule Engine?

A configurable rule engine evaluates business logic defined as structured data rather than code. Rules are stored in a database, loaded at runtime, and can be updated and hot-reloaded without a deployment, enabling product and operations teams to change behavior independently of engineering.

Rule Table Schema

Rule (
  id          UUID PRIMARY KEY,
  name        VARCHAR(255),
  priority    INT,             -- lower number = higher priority
  conditions  JSONB,           -- condition groups
  actions     JSONB,           -- actions to execute on match
  enabled     BOOLEAN,
  version     INT,             -- incremented on each update
  created_at  TIMESTAMPTZ
)

Condition Schema

Each condition is a JSON object with three fields:

{
  "field":    "user.country",
  "operator": "eq",
  "value":    "US"
}

Supported operators:

  • Equality: eq, neq
  • Numeric: gt, gte, lt, lte
  • Set membership: in, not_in
  • String: contains, starts_with
  • Null check: is_null

Conditions are grouped: AND logic within a group, OR logic between groups.

Action Schema

{
  "type":   "send_notification",
  "params": { "channel": "slack", "template": "fraud_alert" }
}

Supported action types:

  • set_field — write a value into the rule context
  • add_tag — append a tag to the context entity
  • send_notification — trigger a notification via configured channel
  • call_webhook — POST context data to an external URL
  • block — halt processing and return a blocked response
  • route_to — direct the entity to a specified queue or workflow

Evaluation Algorithm

rules = load_rules_ordered_by_priority()

for rule in rules:
    if not rule.enabled:
        continue
    if evaluate_conditions(rule.conditions, context):
        execute_actions(rule.actions, context)
        if rule.stop_on_match:
            break   # first-match mode
        # else continue to next rule (chain mode)

Field Resolution

Fields use dot-notation paths into the rule context, which is an arbitrary key-value map:

context = {
  "user": { "country": "DE", "age": 34 },
  "order": { "amount": 250.00, "currency": "EUR" }
}

resolve("order.amount", context)  ->  250.00
resolve("user.country", context)  ->  "DE"

Hot Reload via Redis Pub/Sub

Rules are cached in application memory with a 30-second TTL. When a rule is created, updated, or deleted in the database, the admin service publishes an invalidation message to a Redis channel. All evaluator instances subscribe and flush their local cache immediately:

-- On rule update:
PUBLISH rule-invalidations "{"rule_id": "uuid"}"

-- Subscriber handler:
on message(channel, data):
    cache.delete(data.rule_id)
    -- next evaluation triggers fresh DB load

Rule Versioning and Audit

Every update to a rule increments its version integer. Previous versions are retained in a RuleVersion audit table:

RuleVersion (
  rule_id     UUID,
  version     INT,
  conditions  JSONB,
  actions     JSONB,
  changed_by  UUID,
  changed_at  TIMESTAMPTZ,
  PRIMARY KEY (rule_id, version)
)

Test Mode

Rules can be evaluated against a sample context without executing any actions. The evaluator returns which rules matched and which conditions passed or failed, enabling safe rule authoring before enabling in production.

POST /rules/evaluate-dry-run
{
  "context": { "user": { "country": "FR" }, "order": { "amount": 500 } }
}

Response:
{
  "matched_rules": ["uuid-1", "uuid-3"],
  "skipped_rules": ["uuid-2"],
  "actions_would_execute": [...]
}

Key Design Considerations

  • Priority integers should be spaced (e.g., 100, 200, 300) to allow inserting rules between existing ones without renumbering.
  • The evaluator is stateless; all state lives in the context map passed by the caller.
  • Webhook action calls are made asynchronously via a job queue to avoid blocking the evaluation response.
  • Rule changes require a two-step publish: save to DB first, then publish invalidation, so subscribers always read a consistent state.

See also: Stripe Interview Guide 2026: Process, Bug Bash Round, and Payment Systems

See also: Atlassian Interview Guide

See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering

See also: Shopify Interview Guide

Scroll to Top