Infrastructure

The Payments Service runs as 16 AWS Lambda functions backed by DynamoDB tables, SQS queues, and Kinesis streams. All infrastructure is managed via Terraform in deploy/.

Lambda Functions

All Lambdas share the same compiled binary distribution (dist/) and are deployed using the fmtf-module-lambda Terraform module. Timeouts marked with * are derived from an SQS queue’s visibility_timeout_seconds (worker = 90%, prenoter = 50%).

Lambda Trigger Timeout Memory Max Concurrency

api

API Gateway (IAM + JWT)

300 s

256 MB (512 MB in test)

prenoter

SQS prenotes

30 s*

128 MB

5

check-ach-scheduler

CloudWatch (15:30 UTC daily)

900 s

2048 MB

check-ach-worker

SQS check-ach

54 s*

128 MB

5

usio-scheduler

CloudWatch (every 30 min, prod only)

30 s

128 MB

usio-syncer

SQS usio-sync

540 s*

1024 MB

5

blocklist-remover

SQS blocklist-remove

540 s*

128 MB

5

kinesis-feeder

DynamoDB Streams (prod-payments)

840 s

128 MB

jpm-webhook-handler

API Gateway (webhooks.floatme.io)

300 s

128 MB

jpm-webhook-processor

SQS jpm-webhooks

540 s*

128 MB

5

blocklist-handler

Kinesis prod-payments

840 s

128 MB

balance-reporter

CloudWatch (13:00 UTC daily + hourly, prod only)

60 s

128 MB

jpm-syncer

CloudWatch (13:00 UTC daily)

600 s

128 MB

usio-refresh-scheduler

CloudWatch (15:00 UTC daily)

600 s

128 MB

1

usio-refresh-worker

SQS usio-refresh

54 s*

128 MB

5

debit-card-fixer

SQS debit-fixer

30 s*

128 MB

5

kinesis-feeder and blocklist-handler are deployed in the legacy DynamoDB region (us-east-1). All other Lambdas run in the primary region (us-west-2 in test, us-east-2 in prod).

DynamoDB Tables

Full schema details (keys, GSIs, attribute types, access patterns) are in DynamoDB Tables.

Table Primary Key Purpose

prod-payments

confirmation_id (PK)

Payment records — all payment types, statuses, and event tracking.

pinless-default-card

user_id (PK)

Usio debit/credit tokens for pinless payments.

bank-accounts

user_id + account_id (PK+SK)

KMS-encrypted bank account numbers and routing numbers.

usio-debit-refunds

refund_confirmation_id (PK)

Usio refund transaction records.

bank-account-history

user_id (PK)

History of bank account changes per user.

SQS Queues

Each queue has a corresponding DLQ. All DLQs have a 900-second visibility timeout.

Queue Producer Consumer Visibility Timeout DLQ Receive Count

site-payments-service-prenotes

Callers via API

prenoter

60 s

10

site-payments-service-usio-sync

usio-scheduler

usio-syncer

600 s

10

site-payments-service-check-ach

check-ach-scheduler

check-ach-worker

60 s

1

site-payments-service-blocklist-remove

Callers (bank account update events)

blocklist-remover

600 s

10

site-payments-service-jpm-webhooks

jpm-webhook-handler

jpm-webhook-processor

600 s

10

site-payments-service-usio-refresh

usio-refresh-scheduler

usio-refresh-worker

60 s

1

site-payments-service-debit-fixer

External callers

debit-card-fixer

60 s

1

check-ach, usio-refresh, and debit-fixer queues use maxReceiveCount = 1, meaning a single processing failure sends the message directly to the DLQ without retry. For check-ach and usio-refresh this is intentional — each message represents a specific date/account batch and retrying could cause duplicate state updates. debit-fixer jobs are manually enqueued one-off repairs where retry semantics are the operator’s responsibility.

Kinesis Streams

Stream Producer Consumers Purpose

prod-payments

kinesis-feeder

blocklist-handler (this service), subscription-service.achhandler

Payment lifecycle events. The feeder reads the prod-payments DynamoDB stream and publishes fmsdk.Event records keyed by each payment’s event_type field.

See Event Flows for the full list of published event types and payload structure.

CloudWatch Schedules

Rule Target Lambda Schedule Notes

usio-transactions-syncer

usio-scheduler

Every 30 min

Prod only. Triggers Usio transaction sync for the past 35-minute window.

check-ach

check-ach-scheduler

15:30 UTC daily

Polls JPM and Usio for ACHSENT payment resolution.

site-usio-token-refresh-event

usio-refresh-scheduler

15:00 UTC daily

Refreshes expiring Usio debit/credit tokens.

balance-reporter

balance-reporter

13:00 UTC daily

Prod only. Posts merchant account balances to Slack.

balance-reporter-hourly

balance-reporter

Every 1 hour

Prod only. Posts condensed hourly balance update to Slack.

jpm-syncer

jpm-syncer

13:00 UTC daily

Syncs JPM transaction details to DynamoDB.

Terraform Structure

All infrastructure lives in deploy/. The top-level files correspond to AWS resource groups:

File Contents

lambda.tf

All Lambda function modules (16 total). Also defines the API Gateway v2 (HTTP API).

sqs.tf

All SQS queues and their DLQs (7 queues + 7 DLQs).

kinesis.tf

Kinesis stream data source reference (prod-payments).

cloudwatch_rules.tf

EventBridge rules and targets for all scheduled Lambda triggers.

api.tf

REST API Gateway (v1) for legacy endpoints. The primary API uses API Gateway v2 (HTTP API) defined in lambda.tf.

kms.tf

KMS key reference for bank account encryption.

secrets.tf

Secrets Manager data source references (Usio, JPM, Plaid credentials, etc.).

vpc.tf

VPC, subnet, and security group data source references for API Gateway VPC link.

debit_fixer.tf

debit-card-fixer Lambda module (split out separately).

usio_refresher.tf

usio-refresh-scheduler and usio-refresh-worker Lambda modules.

variables.tf

Input variables: environment, application, service_version, etc.

Deployment

v2 (Current)

The main branch is the current v2 default branch. The code in the main branch is automatically deployed to the test environment in us-west-2 with the github workflow in .github/workflows/deploy.yaml.

We use release-please to keep a long running release PR of changes since the last release. Merging this PR will create a draft GitHub release that, once published, deploys to production in us-east-2.

v1 (Legacy)

The develop and master branches use the old deployment system. Under this system, the develop branch is deployed to test and master is deployed to production.