Designing a Rule-Based Decision System for Pet Health Alerts

Designing a Rule-Based Decision System for Pet Health Alerts

Introduction

At Hoomanely, the goal is straightforward: give pet parents better tools for spotting problems early. From drinking patterns to early temperature anomalies, our systems turn raw sensor data into clear, usable health insights. Behind every one of those insights sits a decision layer we call the rule-based engine, which bridges raw telemetry and medically meaningful alerts.

Rather than leaning on ML for every small decision and losing explainability along the way, we built a deterministic engine that encodes veterinary knowledge, environmental context, and dog-specific traits. This post covers how our bitmask-based rule engine works, why it's fast and scalable, and how storing raw categorical fields alongside partial-match indexing fits into the pipeline running Hoomanely today.

Diagram of raw sensor telemetry flowing into a rule-based decision layer producing health alerts
Diagram of raw sensor telemetry flowing into a rule-based decision layer producing health alerts

Turning multidimensional pet data into real-time, reliable alerts

Dogs generate dozens of signals a day: drinking and eating sessions, hourly and daily consumption, eye temperature readings, audio cues like gulps, barks, and coughs, plus season, weather, humidity, and breed- or age-specific risk factors.

A working system has to answer something like: if a senior French Bulldog drinks less on a humid night, should we warn the parent? Doing that safely and at scale means fast lookups under 10ms, support for hundreds of rules, deterministic output, easy extension when vets add new patterns, and low compute cost whether on edge or cloud. Traditional relational queries with ten or twelve conditions run slow, and ML classifiers are opaque and hard to justify in a medical context. We needed something in between.

Diagram contrasting relational query lookups with a bitmask-based rule engine
Diagram contrasting relational query lookups with a bitmask-based rule engine

A bitmask-driven rule engine

We compress each rule into a single 64-bit mask, where each bit represents one categorical attribute: breed, age bucket, gender, season, time of day, temperature bucket, AQI bucket, or allergy and medical flags. We then combine the deviation direction (plus or minus) with the mask into a composite key:

<deviation>:<bitmask>

This key lets DynamoDB fetch matching rules with a single indexed lookup.

Converting a CSV into 500-plus production rules

Our vet team provides a CSV of rule conditions, and for each row we generate a deterministic 64-bit bitmask, a composite lookup key such as "-:5915773948032745472", a DynamoDB rule item, and expanded categorical fields as part of our actual storage pipeline. A sample item looks like this:

{
  "parameter": "daily_water_consumption",
  "lookup_key": "-:5915773948032745472",
  "deviation": "-",
  "bitmask": 5915773948032745472,
  "breed": "French_Bulldog",
  "age_group": "Senior",
  "season": "Summer",
  "temp_bucket": "HOT",
  "aqi_bucket": "HAZARDOUS",
  "severity": "SOS",
  "message": "Decreased water intake in hot conditions raises dehydration risk.",
  "rule_id": "rule_0005"
}

Runtime lookup: fast and deterministic

When telemetry arrives, say hourly water consumption drops, we compute the dog's bitmask, combine it with the deviation, and filter matches with a simple bitwise check:

(rule.mask & dog_mask) === rule.mask

Then we query DynamoDB directly:

KeyConditionExpression: "parameter = :p AND begins_with(lookup_key, :dev)"

This guarantees that rules only match when every one of their conditions is satisfied, irrelevant fields never block a match, and a single query returns a deterministic result.

A high-speed, scalable decision layer

The finished engine handles over 500 rules in one table, resolves lookups in under 10ms, produces deterministic medical alerts, has zero rule collisions since bitmasking makes collisions structurally impossible, and extends instantly whenever a new CSV row comes in. It now powers daily hydration and nutrition monitoring, context-aware temperature alerts, senior-dog-specific risk detection, and audio-based anomaly notifications.

Architecture diagram of the production rule engine at scale
Architecture diagram of the production rule engine at scale

Where we could take this further

The core engine is already production-ready, but two enhancements would extend it further. Storing raw categorical fields, like breed, age group, gender, season, time of day, temperature bucket, AQI bucket, and medical flags, would make debugging easier, support rule editing and auditing, enable richer analytics such as "all hydration rules for Summer," and give internal vet workflows better visualization tools.

A secondary index for partial matching, a GSI supporting semantic queries, would let us browse all rules for a breed, run consistency checks, generate near-miss suggestions, and support vet dashboard filtering. Neither is required for correctness; they simply widen what the system can do over time.

Illustration of a secondary index enabling partial-match rule queries
Illustration of a secondary index enabling partial-match rule queries

Why bitmasking over hashing

This system runs on bitmasks rather than hashes, which has real advantages: zero collisions, O(1) comparisons using simple AND operations, easy extension by adding more bits, and deterministic behavior by design. That combination is what makes the current setup as robust as it is.

Takeaways

  • A rule-based engine matters when ML can't offer medically safe explainability.
  • Bitmasking compresses complex conditions into fast, deterministic checks.
  • DynamoDB composite keys let us query hundreds of rules in a few milliseconds.
  • Storing raw categorical fields and adding a GSI is part of the actual pipeline supporting analytics, debugging, and long-term growth.
  • This decision layer powers health intelligence across EverBowl and the wider Hoomanely ecosystem.