Event Flows
The Float Service participates in the FloatMe event-driven architecture in three ways: it publishes lifecycle events to EventBridge for downstream consumers, it consumes scheduled EventBridge rules to trigger collection and prenote runs, and it reacts to external signals (income and balance events) via SQS.
Overview
Float Service
│
┌───────────────────────┼───────────────────────┐
│ │ │
▼ ▼ ▼
Publishes Consumes Consumes
EventBridge scheduled rules SQS queues
events (outbound) (inbound triggers) (inbound signals)
│ │ │
▼ ▼ ▼
Downstream Collections Scheduler Webhook Workers
services invoked on schedule react to income
consume to queue collection and balance events
user_float_created runs to SQS in real time
Events Published
user_float_created
Published to EventBridge by the API Lambda immediately after a float record is successfully written to RDS.
| Field | Value |
|---|---|
Event source |
|
Event type |
|
Payload |
Full float object: |
Trigger |
|
Downstream services (e.g. underwriting, analytics) subscribe to this event via their own EventBridge rules. The Float Service does not manage those subscriptions.
Scheduled Collections
Two CloudWatch EventBridge rules trigger the prod-floats-collections-scheduler Lambda on weekdays. The scheduler queries RDS for qualifying floats at each stage and enqueues them to the prod-floats-collections SQS queue for the Collections Worker to process.
EventBridge Rules
| Rule | Schedule (UTC) | Input | Effect |
|---|---|---|---|
|
9:30 AM Mon–Fri |
|
Triggers T-1 Day ( |
|
8:30 AM Mon–Fri |
|
Triggers the Daily Retry run. Queries for floats in |
Scheduler → Worker Flow
EventBridge rule fires
│
▼
Collections Scheduler Lambda invoked
│
▼
Query RDS for qualifying floats
TODAY6AM: status=SCHEDULING, due date <= today
TOMORROW: status=SCHEDULING, due date = next business day
RETRY: status IN (RETRY, FAILED, ACHFAILED, UNCOLLECTABLE), due date passed
│
▼
For each qualifying float:
Enqueue Collection{float, processType} to SQS
│
▼
Collections Worker Lambda dequeues and processes
(see xref:collections.adoc[Collections Engine] for decision logic)
Webhook Worker (Income Detection)
The prod-floats-webhook-worker Lambda reacts to income detection events from the Insight Service. When income is detected for a user, the worker checks whether that user has a float in RETRY status and, if so, attempts immediate collection.
Event Path
Insight Service detects income for a user
│
▼
EventBridge rule: income-detected-rule
│
▼
SQS: prod-floats-income-event-tap
│
▼
Webhook Worker Lambda invoked
Event payload: {UserID}
│
▼
GrowthBook flag floats.webhook.balance.enabled?
Yes ──► skip (balance worker handles collection for this user)
No ──► proceed with income-triggered collection
│
▼
Check user has float in RETRY status
Enforce daily attempt cap and balance threshold ($50)
Attempt collection (see xref:collections.adoc#webhook-triggered-collection[Webhook-Triggered Collection])
floats.webhook.balance.enabled is a rollout flag that routes users to the balance worker path instead. When it is true for a user, the webhook worker skips that user entirely, and the balance worker handles collection when a balance update event arrives.
|
Balance Webhook Worker
The prod-floats-webhook-worker-balance Lambda reacts to balance update events from the Transactions Service. It applies a more conservative balance check before attempting collection, making it suitable for users whose income detection path has been migrated to balance-based triggering.
Event Path
Transactions Service publishes balance update event
(filter: new_account events from txn-service.feeder)
│
▼
EventBridge rule: balance-detected-rule
│
▼
SQS: prod-floats-balance-event-tap
│
▼
Balance Worker Lambda invoked
│
▼
GrowthBook flag floats.webhook.balance.enabled?
No ──► skip (this user is still on the income webhook path)
Yes ──► proceed with balance-triggered collection
│
▼
Check user has float in RETRY status
Enforce daily attempt cap, ACH attempt cap, and balance threshold
(balance > float fee + float amount + $20 buffer, configurable)
Attempt collection (see xref:collections.adoc#balance-update[Balance Update])
GrowthBook Flags
| Flag | Effect |
|---|---|
|
Routes a user from the income webhook worker to the balance webhook worker. When |
|
Balance buffer applied on top of fee + amount before attempting collection. Default: $20. |
|
When |
|
Array of institution IDs for which pinless debit routing is supported in the balance worker. |
Prenote Scheduling
The prod-floats-prenote-scheduler Lambda runs on its own EventBridge schedule, independent of the collections schedule. It submits zero-dollar ACH prenotes ahead of the due date to validate account numbers with the processor before real collection debits are submitted.
EventBridge Rule
| Rule | Schedule (UTC) | Effect |
|---|---|---|
|
12:30 PM Mon–Fri |
Fires 3 hours after the collections runs. Triggers |
Scheduler → Worker Flow
EventBridge rule fires (Mon–Fri, 12:30 UTC)
│
▼
Prenote Scheduler Lambda invoked
│
▼
Determine target due date
Mon/Tue: run_time + 3 calendar days
Wed/Thu/Fri: run_time + 5 calendar days (skips weekend)
│
▼
Query RDS replica: SCHEDULING floats due on target date
│
▼
For each float, evaluate GrowthBook flag floats.prenotes for user_id
Keep if flag is enabled for the user (default false)
│
▼
SendMessageBatch ──► SQS: prod-floats-prenotes
│
▼
Prenote Worker Lambda dequeues (concurrency capped at 3)
Fetch user from User Service
Call Payments.SubmitUsioPrenote (UsioAccount: float-debit)
Batch-item failure on error (SQS retries up to maxReceiveCount)
The prenote path is decoupled from collection state. It does not acquire the per-user collection lock, write to collection-history, or change float status. Returns (e.g. closed accounts) are tracked by the Payments Service.
|
Reporter
The prod-floats-reporter Lambda generates a daily float origination summary and posts it to Slack.
Flow
EventBridge rule fires (daily, 12:00 UTC)
│
▼
Reporter Lambda invoked
│
▼
Query RDS read replica
Group floats by date and loan type (ACH, PINLESS, RTP)
Aggregate counts and amounts
Window: last 10 days
│
▼
Format plain-text table:
Date (Mon YYYY-MM-DD) | ACH total | Pinless total | RTP total
│
▼
Post to Slack channel: #feed-fm-collections
| The reporter is enabled in production only. It is disabled in non-production environments via its EventBridge rule schedule. |
Related Pages
-
Collections Engine — Full decision logic for each collection stage
-
ACH Processing — Kinesis-based ACH settlement callbacks
-
Float Lifecycle — When
user_float_createdis published relative to float creation -
Architecture — System context diagram showing all inbound and outbound event paths