Continuous Float Increase (CFI)

CFI adjusts a user’s float limit from their behavior. The check runs in the rule runner — on both the event-driven and instant paths, before rules execute — so the rules evaluate against the (possibly updated) profile. Source: pkg/rulerunner/runner.go, pkg/rulerunner/handler.go

A separate, score-based limit assignment — Float Tiers — supersedes the stored CFI limit for users flagged into underwriting.float_tiers.rollout. CFI still runs and saves limit changes for them, so the stored profile keeps tracking their behavior, but CheckForFloatIncrease reads the flag (live — it runs before any score exists) and does not send them the underwriting_float_limit_updated Segment event: their limit comes from the assignment, so the notification would describe a limit they are not on. See Float Tiers.

Inputs

Metric Definition

Float rank

Count of the user’s COMPLETED floats (uncapped; the highest threshold used is 8)

Total float rank

Count of all floats regardless of status — used only by ExactFloatRank (first-float) rows

Subscription rank

ActiveSubscriptionData.Length from subscription-service, passed through unchanged

Paid subscription count

COMPLETED subscriptions in the last 6 months, excluding the user’s reactivation month

Reactivating user

Membership reactivation date within the last 6 months

Account balance

Available balance (cents)

Highest float

Largest float amount the user has taken

Source: pkg/rulerunner/increase.go (getCheckData, countSubscriptionsWithOptions)

The IncreaseChecks table

Rows are scanned backward (highest tier first); the first row whose gates all pass sets the target limit. Rank/previous-float/reactivator/flag gates always apply; balance, EWA, and paid-subscription gates apply only when the row would be an increase over the current limit. The $20 floor row passes for everyone. CFI tops out at $100: $200 has no row — it is offered only by the response ladder, from an enforced Float Tiers assignment or the $200 qualification — and neither does $150 (Float Profiles).

Row Amount Min sub rank Min float rank Min prev float Min balance Extra gates

paused_cancelled_sub_rank_0_amt_20

$20

0

0

—

—

none (floor)

sub_rank_1_amt_20

$20

1

0

—

—

—

sub_rank_2_float_rank_3_prev_20_amt_30

$30

2

3

$20

—

—

sub_rank_3_amt_30

$30

3

0

—

—

—

first_float_ewa_1_amt_30

$30

1

0

—

—

EWA borrow >= 1 and repaid >= 1; first float only (ExactFloatRank)

sub_rank_4_amt_40

$40

4

0

—

—

—

sub_rank_6_float_rank_3_prev_40_amt_50

$50

6

3

$40

—

—

sub_rank_7_amt_50

$50

7

0

—

—

—

first_float_ewa_4_amt_50

$50

1

0

—

—

EWA borrow >= 4 and repaid >= 4; first float only

first_float_balance_1500_amt_50

$50

1

0

—

$1,500

first float only

reactivator_rule_2_amt_50

$50

1

1

—

—

reactivating user, >= 1 paid subscription, underwriting.cfi.rules.enabled flag

sub_rank_8_float_rank_6_prev_50_balance_500_amt_80

$80

8

6

$50

$500

—

sub_rank_8_float_rank_6_prev_75_balance_2000_amt_100

$100

8

6

$75

$2,000

—

Source: pkg/rulerunner/models.go (balance constants are cents; amounts and previous floats are dollars)

Applying the result

CFI decision flow
  • Increase (target > current limit): profile tiers up to the target are enabled (SetToLimit), the profile is saved with the deciding row name in last_cfi_rule_name, and — only after a successful save, and not for pre-active (PROCESSING/PAUSED) or Float Tiers users — the Segment event underwriting_float_limit_updated (increased: true) is sent. Metric underwriting.cfi.limit.increased.

  • Decrease (target < current limit): applied only for cfi_enabled users; non-CFI users keep their limit (underwriting.cfi.decrease.ineligible). Decreases are driven by the always-applied gates only. Metric underwriting.cfi.limit.decreased, same Segment event with increased: false.

  • No change: nothing saved; underwriting.cfi.limit.no_update.

saveNewFloatProfile sets cfi_enabled: true on every save, so a non-CFI user’s first increase opts them into future decreases. Source: pkg/rulerunner/increase.go

Next-increase requirements

GetNextIncreaseRequirements (pure function over the stored cfi_state) tells the API what the user still needs for the next tier: it picks the first row above the current limit, skipping first-float rows, and reports the missing floats/subs/previous-float deltas (a $75 previous-float requirement is reported as $80). Returned on the eligibility and loan endpoints, except for users whose ladder is not the stored CFI limit: an enforced Float Tiers assignment, or the $200 qualification while it raises the ladder (Float Decision). Source: pkg/rulerunner/increase.go