DynamoDB Tables

The Float Service uses four DynamoDB tables. Three legacy tables (collection-history, locks, requirements-bypass) are accessed via the DYNAMO_LEGACY_REGION region and were created before the current single-table design was adopted. The primary table (site-float-service) uses a single-table design and is accessed via DYNAMO_REGION.

collection-history

Region: DYNAMO_LEGACY_REGION

An append-only audit log of every collection attempt. One record is written per attempt, regardless of outcome. Used by the collections engine to enforce attempt limits and reconstruct collection history via the API.

Attribute DynamoDB Tag Description

loan_id

PK

Float ID. Maps to loan_id in the RDS floats table.

run_time

SK

Unix nanosecond timestamp of when the attempt was made.

user_id

Owning user’s ID.

due_date

The float’s original due date (YYYY-MM-DD).

run_date

The calendar date of the attempt (YYYY-MM-DD). Used by daily attempt limit checks.

process

The collection stage that triggered this attempt. See Process Values.

outcome

Result of the attempt. See Outcome Values.

confirmation_id

Payment processor confirmation ID for the attempt. Present when a payment was submitted.

ach_model_override

(Optional) Whether the ACH routing ML model decision was manually overridden for this attempt.

ach_model_version

(Optional) Version of the ACH routing ML model used.

ach_model_features

(Optional) Map of feature name → value fed to the ML model for this attempt.

ach_model_probability

(Optional) The model’s predicted probability score for ACH success.

Access Patterns

Query by float ID to retrieve all attempts for a given float:

GetByFloatID(ctx, floatID)  →  QueryByPK(loan_id = floatID)

Process Values

Value Description

TOMORROW

T-1 Day run — float due the next business day

TODAY6AM

Due Date run — float due today

RETRY

Daily Retry run — float in RETRY status past its due date

WEBHOOK

Income detection webhook run

SUPPORT

Manual status update via the API (e.g. PATCH /{user_id}/floats/{float_id})

Outcome Values

Value Description

ACHSENT

ACH debit was submitted to the payment processor.

COMPLETED

Collection was successful (pinless or ACH settled).

RETURNED

ACH debit was returned by the bank (e.g. NSF, account closed).

DEFAULTED

Float was marked as defaulted due to attempt limits or age threshold.

locks

Region: DYNAMO_LEGACY_REGION (also accessible via dedicated DYNAMO_LOCK_REGION)

Distributed locking table used by all collection Lambdas to prevent concurrent collection attempts on the same user’s float. Backed by the cirello.io/dynamolock client.

Attribute DynamoDB Tag Description

PartitionKey

PK

Lock key in the format loan-processing:user_id:{userID}.

data

Unix nanosecond timestamp (as bytes) of when the lock was acquired.

deleteOn

TTL timestamp for automatic record expiry.

leaseDuration

Duration of the lock lease.

owner

Identifier of the lock owner (Lambda instance).

recordVersionNumber

Version counter used for optimistic locking to prevent split-brain.

A lock is held with a 60-second lease and a 1-second heartbeat. If a lock cannot be acquired, the collection attempt is skipped without modifying the float’s status. This ensures only one Lambda instance processes a given user’s float at any time, even when scheduled and webhook paths fire simultaneously.

requirements-bypass

Region: DYNAMO_LEGACY_REGION

Stores per-user eligibility overrides. When a bypass record exists for a user and has not expired, the float creation flow skips the standard requirements check. Managed via the POST/GET/DELETE /{user_id}/bypass API endpoints.

Attribute DynamoDB Tag Description

user_id

PK

Owning user’s ID.

expiration_date

Date the bypass expires (YYYY-MM-DD). The bypass is considered inactive after this date.

reason

Internal note describing why the bypass was granted.

Access Patterns

Get(ctx, userID)               →  GetItem(user_id = userID)
Save(ctx, bypass)              →  PutItem
Remove(ctx, userID)            →  DeleteItem(user_id = userID)

prod-float-service (Single-Table Design)

Region: DYNAMO_REGION — table name from DYNAMO_TABLE env var (default: {environment}-float-service)

This table is currently not being used for anything.