ACH Processing
The site-floats-ach-handler Lambda consumes the prod-payments Kinesis stream and processes ACH settlement callbacks for float disbursements and collection attempts. It is the mechanism by which floats leave ACHSENT — to COMPLETED, RETRY, or DEFAULTED (see Float Statuses).
Callback Handling
The Lambda’s Kinesis event-source mapping filters the stream to six event types (source: deploy/lambda.tf):
FLOAT_DEBIT_COMPLETED, FLOAT_DEBIT_COMPLETED_PLAID, FLOAT_DEBIT_RETURNED, FLOAT_CREDIT_COMPLETED, FLOAT_CREDIT_RETURNED, FLOAT_DEBIT_CHARGED_BACK
The handler dispatches on the payment’s Status field:
payment.Status |
Float status | Collection-log outcome | Side effects |
|---|---|---|---|
|
|
|
Digital receipt (Collection-Success Notifications) |
|
|
The ACH return code (e.g. |
User ban on a bannable code (Bannable ACH Return Codes) |
|
|
|
User ban + admin note |
Processing steps per event:
-
Look up the float by the payment’s
loan_id; no match logs and skips the event. -
Idempotency guard: a
COMPLETEDevent for a float alreadyCOMPLETEDis skipped entirely — no status update, collection log, receipt, or recalculation. -
Update the float in RDS: new status + the processor confirmation ID.
-
Write a collection-history row (schema) —
processisCheck-ach-clearedfor debit events,Chargeback-detectorfor chargebacks. -
On a bannable return or chargeback: ban the user (User Service) and add an account note (Admin Service).
-
Trigger an underwriting recalculation for the user.
| The receipt, ban, admin note, and recalculation are best-effort — failures are logged without halting processing. Failures updating RDS or writing the collection log fail the record, and Kinesis redelivers it. |
Collection-Success Notifications
A settled collection (COMPLETED) sends a digital receipt across three channels:
| Channel | Purpose |
|---|---|
Segment |
Analytics events with float and payment details |
Iterable |
In-app and email notification that the float was collected |
AppsFlyer |
Mobile attribution event |
Bannable ACH Return Codes
A debit returned with one of these codes sets the float to DEFAULTED — NACHA prohibits re-initiating the debit — and bans the user. Any chargeback also triggers a ban. Source: pkg/payments/achhandler.go.
| Return code | Meaning |
|---|---|
|
Unauthorized debit to consumer account using corporate SEC code |
|
Authorization revoked by customer |
|
Payment stopped |
|
Customer advises not authorized |
|
Check truncation entry returned |
|
Corporate customer advises not authorized |
|
Item is ineligible, notice not provided, signature not genuine, or item altered |
Non-bannable return codes (e.g. R01 insufficient funds, R02 account closed) set the float to RETRY with no ban, and it re-enters the retry cycle. A bannable code defaults the float directly — it never passes through RETRY, so it is excluded from all retry collection runs.
|