Fraud Detection
The Float Service runs a series of fraud checks during float creation and uses an embedded ML model to inform ACH routing decisions during collections. Both are controlled by configuration and GrowthBook feature flags, allowing individual checks to be toggled or bypassed without a code deployment.
Float Creation Fraud Checks
Fraud checks run as part of POST /{user_id}/floats after subscription validation and before underwriting. If any enabled check fails, the float is rejected. The results are always saved back to the Payments Service after the attempt, regardless of whether the float was approved or denied.
Check Sequence
Float creation request received
│
▼
1. Check App Version
Minimum build version met? ──No──► ErrAppVersionInvalid ──► reject float
│ Yes
▼
2. Check Float Amount
Amount within allowed maximum? ──No──► ErrFloatAmount ──► reject float
│ Yes
▼
3. Check Recent Floats (queries RDS)
Float taken in last 24 hours? ──Yes──► ErrRecentFloat ──► reject float
Outstanding float exists? ──────Yes──► ErrOutstandingFloat ──► reject float
│ No
▼
4. Check Active Installment Loans (LOC Service)
OPEN or DEFAULTED loan exists? ──Yes──► ErrOutstandingLoan ──► reject float
│ No
▼
5. Payments Service Fraud Check (external)
Check fails? ──Yes──────────────────────► reject float
Connectivity error? ──Yes──────────────► ErrConnectivity ──► reject float
│ Pass
▼
Float creation proceeds (underwriting, disbursement, etc.)
│
▼
Save fraud check results to Payments Service
(skipped if user is bypassed or Payments check had a connectivity error)
Each check is independently enabled. A check that is disabled is skipped and treated as passed.
Checks Reference
| Check | What it validates | External call |
|---|---|---|
App Version |
The requesting app’s build version meets a configured minimum. |
None — validated against a configured value. |
Float Amount |
The requested amount does not exceed the configured maximum. |
None — validated against a configured value. |
Recent Floats |
No float was taken in the last 24 hours and no outstanding float exists for the user. |
RDS — queries the floats table directly. |
Active Installment Loans |
No OPEN or DEFAULTED installment loans exist for the user. |
LOC Service — |
Payments Service |
External fraud check using user context: account ID, float type, install ID, user ID, zip code. |
Payments Service — |
Bypass
Users with an active requirements bypass record (see Bypass & Payback) have the Bypassed flag set to true when fraud checks are invoked. In bypass mode, the underwriting eligibility check is skipped entirely. Individual fraud checks may still run (depending on configuration), but the Bypassed flag is passed to the Payments Service fraud check, which may apply different rules for bypassed users.
Fraud check results are not saved back to the Payments Service for bypassed users.
ACH Routing ML Model
During initial collection attempts, the collections engine can use an embedded logistic regression model to decide whether to route a collection to ACH or pinless debit. This supplements the debit card validity check with a probability-based prediction of ACH success.
Model Details
| Property | Value |
|---|---|
Model name |
|
Algorithm |
Logistic regression |
Decision threshold |
0.50 — route to ACH if predicted probability ≥ 0.50 |
Activation |
GrowthBook flag |
Storage |
Embedded in the Lambda binary as |
Input Features
| Feature | Type | Description |
|---|---|---|
|
Numeric |
The user’s float sequence number (1st float, 2nd float, etc.) |
|
Numeric |
Dollar amount of the float |
|
Numeric |
Days since the user joined the platform |
|
Numeric |
Days elapsed since the user’s previous float was funded |
|
Binary (0/1) |
Whether the user has ever had a successful ACH collection |
|
Numeric |
User’s bank account balance at the time of the collection attempt |
|
Numeric (0–6) |
Day of the week the attempt is made (0 = Monday) |
|
Numeric (0–23) |
Hour of the day the attempt is made |
|
Binary (0/1) |
One-hot encoded institution indicator — over 100 top institutions with fallback categories |
Audit Trail
When the model is used, the collection attempt’s DynamoDB log entry includes:
-
ach_model_version— the model name used -
ach_model_features— the full feature map fed to the model -
ach_model_probability— the raw probability score output -
ach_model_override— whether the model decision was manually overridden
See DynamoDB Tables for the full collection-history schema.
GrowthBook Feature Flags
| Flag | Effect |
|---|---|
|
Enables the embedded ACH routing ML model for a user’s initial collection attempt. When disabled, the collections engine uses the standard debit card validity check alone. |
|
Maximum number of automated ACH attempts before a float is defaulted. Default: 3. |
|
Maximum total collection attempts per day for the webhook balance worker. Default: 3. |
Related Pages
-
Float Lifecycle — Where fraud checks fit in the disbursement flow
-
Collections Engine — How the ACH routing decision is used during collection
-
DynamoDB Tables — Collection history schema including ML model audit fields
-
Bypass & Payback — Requirements bypass and its effect on fraud checks