E-commerce Rule Example

A practical two-ruleset example for checkout routing and fraud filtering.

An e-commerce event may carry checkout, customer, device, merchant, network, cart, and behavioral fields in one nested document. BlazeRules can project only the fields referenced by each ruleset, evaluate them in batches, and emit business-specific decisions without flattening the input manually.

This example separates two operational concerns:

  • checkout routes orders to approval, promotion review, chargeback review, or a general risk queue;
  • fraud blocks automation and account-takeover patterns and evaluates model-derived risk.

Example event shape

{
  "event_id": "evt_018f3d",
  "event_ts_ms": 1784100000000,
  "event_type": "checkout_started",
  "customer": {
    "id": "cus_10420",
    "account_age_days": 4,
    "risk_score": 72
  },
  "cart": {
    "subtotal": 1299.0,
    "discount_amount": 650.0,
    "items": [
      {"sku": "sku_9001", "category": "electronics", "price": 1199.0}
    ]
  },
  "device": {
    "risk_score": 81,
    "fingerprint": "dev_a731",
    "embedding_0": 0.12,
    "embedding_1": -0.04,
    "embedding_2": 0.33,
    "embedding_3": 0.78
  },
  "network": {
    "ip_address": "198.51.100.20",
    "connection_type": "proxy"
  },
  "model_feature_0": 1299.0,
  "model_feature_1": 4.0,
  "model_feature_2": 81.0
}

Checkout decisions

Custom labels let downstream applications route domain-specific outcomes while built-in action values retain standard precedence, score, and risk-band behavior.

schema_version: "2.1"

fields:
  customer.id: {type: entity_key, nullable: false}
  event_ts_ms: {type: timestamp_ms, nullable: false}

decisions:
  default: approve
  precedence:
    - approve
    - score
    - flag
    - review
    - promo_abuse_flag
    - chargeback_review
    - block

ruleset:
  name: Checkout Decisions
  version: "2.0.0-checkout"
  rules:
    - id: checkout_model_review
      action: review
      weight: 30
      conditions:
        model_score:
          model: checkout_risk
          features: [model_feature_0, model_feature_1, model_feature_2]
          op: gte
          value: 0.82

    - id: high_value_new_account
      action: score
      weight: 25
      conditions:
        and:
          - {field: cart.subtotal, op: gte, value: 750}
          - {field: customer.account_age_days, op: lt, value: 14}

    - id: repeated_promo_use
      action: review
      label: promo_abuse_flag
      reason_code: REPEATED_PROMO_USE
      conditions:
        and:
          - op: gt
            expr:
              op: div
              left: cart.discount_amount
              right: cart.subtotal
            value: 0.5
          - window:
              entity_field: customer.id
              function: count
              duration_seconds: 3600
              op: gte
              value: 3

    - id: chargeback_item_review
      action: review
      label: chargeback_review
      conditions:
        array_any:
          path: cart.items
          where:
            and:
              - {field: price, op: gte, value: 1000}
              - {field: category, op: eq, value: electronics}

Fraud decisions

The fraud ruleset can run as a separate agent instance or engine shard with its own rules, model registrations, output sink, and window state.

schema_version: "2.1"

lookups:
  blocked_devices:
    type: string_set
    path: ../lookups/blocked_devices.csv

decisions:
  default: approve
  precedence: [approve, flag, review, account_takeover, bot_block, block]

ruleset:
  name: Fraud Decisions
  version: "2.0.0-fraud"
  rules:
    - id: fraud_model_block
      action: block
      weight: 70
      conditions:
        model_score:
          model: fraud_risk
          features: [model_feature_0, model_feature_1, model_feature_2]
          op: gte
          value: 0.92

    - id: proxy_automation
      action: block
      label: bot_block
      conditions:
        and:
          - {field: network.connection_type, op: in, values: [vpn, proxy]}
          - {field: http.user_agent, op: regex, value: "(?i)(bot|crawler|headless)"}

    - id: new_account_risky_device
      action: review
      label: account_takeover
      conditions:
        and:
          - {field: customer.account_age_days, op: lt, value: 7}
          - {field: device.risk_score, op: gte, value: 75}
          - {field: device.fingerprint, op: in_lookup, lookup: blocked_devices}

    - id: known_device_cluster
      action: review
      conditions:
        vector_distance:
          dims:
            - device.embedding_0
            - device.embedding_1
            - device.embedding_2
            - device.embedding_3
          metric: cosine
          reference: [0.12, -0.04, 0.33, 0.78]
          op: gte
          value: 0.94

Run both HTTP instances

Register each model under the exact name referenced by its ruleset:

blazerules_agent \
  --name checkout \
  --rules rulesets/checkout.yaml \
  --model checkout_risk=models/checkout_risk.onnx \
  --input http \
  --port 9480 \
  --output ndjson \
  --output-path logs/checkout.ndjson

blazerules_agent \
  --name fraud \
  --rules rulesets/fraud.yaml \
  --model fraud_risk=models/fraud_risk.onnx \
  --input http \
  --port 9481 \
  --output arrow \
  --output-path logs/fraud.arrow

Both instances accept batches at /v1/logs. Keep entity-affine traffic on the same instance/shard when window rules are enabled.

What each feature contributes

Business requirementRule featureOutput use
High-value order from a new accountnumeric + nested fieldsadd risk score
Repeated promotion usearithmetic ratio + count windowPROMO_ABUSE_FLAG queue
Expensive risky itemarray_anyCHARGEBACK_REVIEW queue
Learned checkout riskONNX model_scorereview or block
Known device clustervector cosine similaritydevice review
Automated proxy trafficregex + categorical membershipBOT_BLOCK sink
Known bad devicelookup setACCOUNT_TAKEOVER review

The dashboard reads the resulting decision logs and can separate rulesets, custom decisions, model channels, rule fire rates, and dead-letter records without changing the evaluator's hot path.


Did this page help you?