Event Flows

The Payments Service publishes payment lifecycle events to a Kinesis stream. Downstream services subscribe to this stream to react to payment status changes without polling the API. The service also consumes events from other services via SQS.

How Events Are Published

The kinesis-feeder Lambda bridges the DynamoDB Streams record for prod-payments to the prod-payments Kinesis stream. Every write to prod-payments that triggers a stream record is a potential event — but only records where the event_type field is non-empty are forwarded.

DynamoDB (prod-payments)
 │  DynamoDB Streams (new image on every write)
 ▼
kinesis-feeder (Lambda)
 │  unmarshal payment record from stream image
 │  if event_type == "" → skip (no Kinesis write)
 │  if event_type != "" → build fmsdk.Event
 │    event.ID     = confirmation_id
 │    event.Type   = event_type
 │    event.Source = "PaymentService"
 │    event.Data   = payment object
 ▼
prod-payments Kinesis stream
 │
 ├──► subscription-service.achhandler
 └──► payments-service.blocklist-handler
Most payments are written at submission time with an empty event_type and only trigger a Kinesis event on a subsequent status-update write (e.g. by the webhook processor or check-ach worker). Prenotes are the exception: the prenoter Lambda writes the record with event_type = PRENOTE_SUBMITTED directly at submission, so the submission write itself is forwarded to Kinesis.

Kinesis Event Types

These are the event_type values that appear in Kinesis records from this service. They correspond to the event_type field written to prod-payments when a payment’s status changes.

Event Type Trigger Kinesis Consumer(s)

SUBSCRIPTION_RETURNED

A JPM or Usio subscription ACH payment is returned by the bank. Written by jpm-webhook-processor or check-ach-worker.

blocklist-handler (evaluates return code for auto-block), subscription-service.achhandler

FLOAT_DEBIT_RETURNED

A Usio float ACH debit is returned by the bank. Written by usio-syncer or check-ach-worker.

blocklist-handler (evaluates return code for auto-block), subscription-service.achhandler

SUBSCRIPTION_CLEARED

A subscription ACH payment clears JPM internal review. Written by jpm-webhook-processor.

subscription-service.achhandler

SUBSCRIPTION_COMPLETED

A subscription ACH payment is forwarded to the ACH network by JPM. Written by jpm-webhook-processor.

subscription-service.achhandler

FLOAT_DEBIT_CLEARED

A float ACH debit payment clears. Written by check-ach-worker or usio-syncer.

subscription-service.achhandler

PRENOTE_SUBMITTED

A prenote (zero-dollar ACH) is submitted. Written at submission time.

None (skipped by consumers)

The Kinesis stream supports up to 20 consumers. Currently only 2 are registered. See the feeder.go comment for the current consumer list.

Event Payload Structure

Each event published to Kinesis is an fmsdk.Event (from github.com/floatme-corp/fmsdk/events) with the following structure:

{
  "id":      "<confirmation_id>",    // payment's confirmation_id
  "type":    "<event_type>",         // e.g. "SUBSCRIPTION_RETURNED"
  "source":  "PaymentService",
  "version": "V2",
  "data": {
    // Payment object (same shape as GET /payments/{confirmation_id} response)
    "confirmation_id": "...",
    "user_id":         "...",
    "status":          "FAILED",
    "return_code":     "R02",
    "payment_method":  "ach",
    "payment_type":    "debit",
    "payment_provider":"usio",
    "amount":          15.99,
    "submit_date":     "2025-01-15T20:00:00Z",
    ...
  }
}

The data field is the full payment record serialized from api.Payment. Consumers can inspect data.return_code to determine the reason for a return.

DynamoDB Streams

Only prod-payments has a DynamoDB Stream enabled. The kinesis-feeder Lambda is the sole consumer of this stream.

Table Stream Consumer

prod-payments

New image on every write

kinesis-feederprod-payments Kinesis stream

All other DynamoDB tables in this service do not have streams enabled.

Events Consumed from Other Services

The Payments Service consumes events published by other FloatMe services via SQS queues.

Queue Published By Consumer Lambda

Purpose

site-payments-service-prenotes

External callers (typically float-service or subscription-service)

prenoter

Triggers a zero-dollar prenote submission to JPM or Usio for bank account validation.

site-payments-service-blocklist-remove

Other FloatMe services (bank account update flow)

blocklist-remover

Removes a user from the ACH blocklist when they update their bank account.

site-payments-service-jpm-webhooks

jpm-webhook-handler (internal, enqueued from API Gateway webhook callback)

jpm-webhook-processor

  • Payment Flow — When event_type is set and what triggers a Kinesis publish

  • Payment Syncing — How jpm-webhook-processor and check-ach-worker set the event_type that drives these events

  • Blocklist — How blocklist-handler consumes SUBSCRIPTION_RETURNED and FLOAT_DEBIT_RETURNED events

  • Infrastructure — SQS queue names, visibility timeouts, and Kinesis stream details