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

float-service.api

Event type

user_float_created

Payload

Full float object: id, user_id, type, amount, fee, debit_status, debit_date, credit_id, evaluation_id, created_date, is_custom_payback_date, default_payback_date

Trigger

POST /{user_id}/floats — after RDS write succeeds, before response is returned

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

float-collections

9:30 AM Mon–Fri

{"time": 6}

Triggers T-1 Day (TOMORROW) and Due Date (TODAY6AM) runs. Queries for SCHEDULING floats whose due date is tomorrow or today.

float-collections-retry

8:30 AM Mon–Fri

{"time": 5}

Triggers the Daily Retry run. Queries for floats in RETRY, FAILED, ACHFAILED, and UNCOLLECTABLE statuses whose due date has passed.

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

floats.webhook.balance.enabled

Routes a user from the income webhook worker to the balance webhook worker. When true, webhook-worker skips the user; when false, balance-worker skips the user.

floats.webhook.balance.buffer

Balance buffer applied on top of fee + amount before attempting collection. Default: $20.

floats.webhook.balance.use_calculated_balance

When true, uses a calculated balance rather than the raw reported balance for the threshold check.

floats.pinless.institutions

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

float-prenote-scheduler

12:30 PM Mon–Fri

Fires 3 hours after the collections runs. Triggers prod-floats-prenote-scheduler to enqueue prenote submissions for floats due in 4 business days.

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.
  • Collections Engine — Full decision logic for each collection stage

  • ACH Processing — Kinesis-based ACH settlement callbacks

  • Float Lifecycle — When user_float_created is published relative to float creation

  • Architecture — System context diagram showing all inbound and outbound event paths