Rules Reference

Every rule the engine can run. A rule is a method on rules.RuleReflector dispatched by name (rule_arn); implementations live in pkg/rules/rule_<snake_name>.go. Rules are pure functions of RuleExecutionData — they make no network or GrowthBook calls. Result encoding: DynamoDB.

Rulebook rules

The 25 rules configurable in rulebooks (scripts/yaml_rulebooks/rules.yml); which rulebooks use them: Rulebooks.

Rule Passes when Custom props

RuleAgeOfAccount

Oldest transaction implies account age >= min_age days

min_age

RuleAverageBalance

Mean daily available balance >= threshold (passes without balance data)

available_threshold

RuleBalanceBetweenBounds

User has float rank >= max_float_rank, or balance outside the [min_balance, max_balance] deny band

max_float_rank, min_balance, max_balance

RuleBalanceRequirement

Available or current balance >= threshold; optional float-count gate

min_available, min_current, min_num_of_floats

RuleCollectionsErrors

Collection-error : completed-float ratio ⇐ max_error_ratio

max_error_ratio

RuleCompetitorEwa

Competitor-EWA borrow/repayment counts in the window meet minimums

number_of_days, min_advance_amount, min_inflows, min_repayments, min_floats

RuleConsecutiveSubscriptions

Most recent min_consecutive_subscriptions non-future subscriptions all COMPLETED

min_consecutive_subscriptions

RuleEssentialSpend

Enough qualifying transactions in essential categories within the window

required_float_rank, required_dollar_amount, required_number_of_transactions, essential_categories, days_to_consider

RuleEWADollarAmount

Competitor-EWA borrowed and repaid dollar totals meet minimums

days_to_consider, required_min_borrow_amount, required_min_repayment_amount, min_advance_amount

RuleFloatRank

Completed-float count within [min_float_rank, max_float_rank]; also emits the borrow-history features in RuleFloatRank borrow-history features

min_float_rank, max_float_rank

RuleGoodStanding

Active user, no outstanding float, no open loan — see RuleGoodStanding

—

RuleInstitutionCheck

User not at a listed institution, or balance >= min_balance

institution_list, min_balance

RuleLowTransactions

Average transactions/day >= threshold over the window, with float-rank exemption

days_to_consider, average_transactions, float_rank, run_chime_varo_check

RuleMLPaybackPrediction

ML default probability within threshold; optional float-count scoping

min_prediction_score, max_float_count, deny_non_applicable

RuleMLPaybackPredictionVariableThreshold

Same, threshold picked by completed-float count

low_float_threshold, high_float_threshold, min_float_count_for_high_threshold

RuleMultipleAccounts

Related-account count ⇐ max_accounts (first-time floaters only)

max_accounts

RuleOnTimeFloatPayback

Last N floats repaid within the grace period

days_after_float_on_time, required_last_floats_on_time, required_float_rank

RulePayrollSpend

Post-payroll spend within spend_cap_multiplier of qualifying payroll inflows

lookback_days, days_after_payroll, spend_cap_multiplier, min_qualifying_payroll_amount, max_single_txn_percentage, min_qualifying_inflows

RuleRecentFloat

Last float repaid within max_days

max_days

RuleRecurringDepositsAndHighTransfer

Recurring income present and payday transfers ⇐ transfer_ratio of it

min_income, transfer_ratio

RuleSpendVelocity

At most allowed_high_spend_instances of spending > spend_percentage of income after payday

spend_percentage, min_income, days_after_income, allowed_high_spend_instances

RuleSubscriptionRank

Subscription rank >= min_rank, with a sub paid within paid_within_days

min_rank, paid_within_days

RuleSuspiciousHighBalance

Not (balance > threshold on an account younger than min_age_of_account days)

high_account_balance, min_age_of_account

RuleTransferRatio

Transfer transactions ⇐ max_transfer_percentage of activity (skipped below the txn minimum)

days_to_consider, transfer_categories, required_number_of_transactions, max_transfer_percentage

RuleValidDebitCard

User has a valid debit card — see RuleValidDebitCard for the skip cases

—

Source: pkg/rules/, scripts/yaml_rulebooks/rules.yml

The two ML rules above run inside rulebooks against the rule-ML SageMaker endpoint. They are unrelated to Payback Predictor V2, which runs in the API Lambda after the rule engine has decided and can override that decision. The rule runner calls the endpoint once per run, before any rulebook is evaluated, only when SAGEMAKER_ENABLED is true (Infrastructure); otherwise both rules return an error outcome.

Model-feature rules

Registered in pkg/rulerunner/model_feature_rules.go and merged into every rule run regardless of rulebook configuration. Their outcomes feed the payback predictor v2 cold features (ML Feature Pipeline); the stored name is the rule ARN plus a V2/V3 suffix, so they never collide with a rulebook’s own registration.

Stored name Rule Notes

RuleTransactionCategoryFeaturesV3

RuleTransactionCategoryFeatures

Feature-only: category and cash-flow aggregates; always approves

RuleBalanceHistoryV2

RuleBalanceHistory

Feature-only: balance-history metrics; always approves

RuleSubscriptionRankV3

RuleSubscriptionRankModelFeature

Feature-only: parses the CFI-time sub rank out of FloatProfile.Notes; always approves

RuleGoodStandingV2

RuleGoodStanding

Good-standing gate outcome for the model

RuleMLPaybackPredictionV2

RuleMLPaybackPrediction

Threshold 0.0 (feature capture)

RuleFloatRankV3

RuleFloatRank

min_float_rank: 0

RuleCompetitorEwaV2

RuleCompetitorEwa

32-day window, zero minimums

RuleBalanceRequirementV2

RuleBalanceRequirement

Zero thresholds

RuleTransferRatioV2

RuleTransferRatio

32-day window, 100% cap

RuleLowTransactionsV2

RuleLowTransactions

32-day window, 1.6/day

RuleCollectionsErrorsV2

RuleCollectionsErrors

Ratio cap 1.5

RuleAverageBalanceV2

RuleAverageBalance

Threshold 0

RuleEssentialSpendV2

RuleEssentialSpend

Groceries category, zero minimums

Source: pkg/rulerunner/model_feature_rules.go

RuleFloatRank borrow-history features

Beyond its pass/deny result, RuleFloatRank emits borrow-history features onto its outcome. The first four feed the payback predictor v2 cold features; the last two exist for the V2 CFI guardrails and are ignored by the model. Any of them is null when the user has no history to derive it from.

The active SCHEDULING float with no payback date is excluded throughout, so these describe only historical borrows.

Feature Unit Meaning

prior_borrow_count

count

Prior borrows in any status

prior_borrow_on_time_rate

ratio

Share of prior borrows repaid on or before their due date

prior_borrow_max_repaid

dollars

Largest amount ever repaid

days_since_last_repayment

days

Age of the newest payback date; null when that date is in the future, which only happens on a data-quality issue

last_repaid_amount

dollars

Amount of the single most recently repaid float

last_repaid_days_late

days

That float’s payback date minus its due date — negative when repaid early, 0 on the due date

The last two describe one float rather than an aggregate, so they can disagree with prior_borrow_max_repaid: a user whose biggest float was two borrows ago reports the smaller, newer amount here. Both are null together, and only for a user with no completed float the rule can date — which covers the new user and the user whose prior float defaulted, since a float that was never repaid has no payback date. Two floats sharing a payback date resolve to the larger amount, so the pair never depends on the order float-service returns.

last_repaid_days_late is measured against the due date truncated to a day, matching the on-time definition behind prior_borrow_on_time_rate: the due date arrives as an RFC3339 timestamp with a time of day while the payback date is date-only, so comparing them raw would read almost every repayment as a day early.

Source: pkg/rules/rule_float_rank.go (computeFloatBorrowFeatures)

RuleGoodStanding

Passes when all of:

  • user status is ACTIVE or PROCESSING — or PAUSED on a reactivation invocation (RuleExecutionData.InvocationType, set by the instant check);

  • no outstanding (non-COMPLETED, non-HOLD) float — with two carve-outs below;

  • no open loan.

Reactivation carve-out: on a reactivation run, outstanding floats whose debit date has passed are discounted — the reactivation charge repays them (repaidOnReactivation, mirroring float-service’s payback). A float due in the future still blocks, and open loans are never discounted.

Early-advance carve-out: the rule discounts one ACHSENT float for a user who cleared an early-advance path and is in the treatment arm; for the float_rank path the rule runs the qualification checks itself. On the passing branch it emits the grant keys, and on both branches the experiment diagnostics. Full design: Early Advance.

Source: pkg/rules/rule_good_standing.go

RuleValidDebitCard

Passes when the user’s debit card is valid; a nil card denies with NODATA. The rule auto-passes for PROCESSING users and for PAUSED/ACTIVE users on a reactivation invocation: the reactivation charge is itself the card check — user-service repays the outstanding float and subscription by debit, so a member whose card cannot be charged never completes reactivation. The card is checked normally on every later event-driven run.

Source: pkg/rules/rule_valid_debit_card.go

Error handling

A rule that errors records error: true with an error_code feature (CALCERR for missing input data) and denies; the rest of the rulebook still runs. How errors roll up to statuses: Rule Engine.