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 |
Total float rank |
Count of all floats regardless of status — used only by |
Subscription rank |
|
Paid subscription count |
|
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 |
|---|---|---|---|---|---|---|
|
$20 |
0 |
0 |
— |
— |
none (floor) |
|
$20 |
1 |
0 |
— |
— |
— |
|
$30 |
2 |
3 |
$20 |
— |
— |
|
$30 |
3 |
0 |
— |
— |
— |
|
$30 |
1 |
0 |
— |
— |
EWA borrow >= 1 and repaid >= 1; first float only ( |
|
$40 |
4 |
0 |
— |
— |
— |
|
$50 |
6 |
3 |
$40 |
— |
— |
|
$50 |
7 |
0 |
— |
— |
— |
|
$50 |
1 |
0 |
— |
— |
EWA borrow >= 4 and repaid >= 4; first float only |
|
$50 |
1 |
0 |
— |
$1,500 |
first float only |
|
$50 |
1 |
1 |
— |
— |
reactivating user, >= 1 paid subscription, |
|
$80 |
8 |
6 |
$50 |
$500 |
— |
|
$100 |
8 |
6 |
$75 |
$2,000 |
— |
Source: pkg/rulerunner/models.go (balance constants are cents; amounts and previous
floats are dollars)
Applying the result
-
Increase (target > current limit): profile tiers up to the target are enabled (
SetToLimit), the profile is saved with the deciding row name inlast_cfi_rule_name, and — only after a successful save, and not for pre-active (PROCESSING/PAUSED) or Float Tiers users — the Segment eventunderwriting_float_limit_updated(increased: true) is sent. Metricunderwriting.cfi.limit.increased. -
Decrease (target < current limit): applied only for
cfi_enabledusers; non-CFI users keep their limit (underwriting.cfi.decrease.ineligible). Decreases are driven by the always-applied gates only. Metricunderwriting.cfi.limit.decreased, same Segment event withincreased: 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