DynamoDB Tables

The Insight Service uses five DynamoDB tables. site-pave is a single-table design holding every insight entity; the others are single-purpose. Regions and consuming Lambdas are in Infrastructure.

site-pave

Every item has string PK and SK attributes and a type discriminator. Keys are built by utils.HashJoinPath, which joins segments with #.

Entities

Entity PK SK TTL Written by Read by

payday

PAYDAY#<user_id>

PREDICTION

2 days

api

api — Same-Day Cache

income_verification

USERS#<user_id>

VERIFICATION

None

api

api — Income Verification

balance (SAVINGS_MONTH)

USERS#<user_id>

SAVINGS_MONTH#<YYYY-MM>

1 year

savings-snapshot

api — Savings Progress

alert

USERS#<user_id>

ALERT#<user_id>

None

balance-alert

balance-alert — Balance Alerts

pave_label

LABEL#<user_id>

PAVE#REFRESH_INSIGHTS

None

feeder

feeder — Feeder

last_page

USERS#<user_id>

LAST_PAGE#REQUEST_ID#<pave_request_id>

5 days

feeder

miner — Miner

insights (mine metadata)

MINE#<user_id>

TIME#<RFC3339>

None

None

api (GET /{user_id}/transactions/expenses)

recurring

USERS#<user_id>

RECURRING#<last_mine>#MERCHANT#<merchant_uuid>#<frequency>#<amount>

due_date + EXPENSE_TTL days

None

api (GET /{user_id}/transactions/expenses)

ritual

USERS#<user_id>

RITUAL#<last_mine>#MERCHANT#<merchant_id>#<frequency>#<amount>

due_date + EXPENSE_TTL days

None

None

income

USERS#<user_id>

INCOME#<user_id>

None

None

None

scores

USERS#<user_id>

CASH_ADVANCE_SCORE#<RFC3339>

ScoreTTL days

None

api (GET /{user_id}/scores/cash_advance)

Source: pkg/dynamo/*.go (one file per entity)

Entities with no writer are Pave-derived caches. recurring and ritual rows age out via TTL; insights and income rows carry no TTL and are never deleted by the service. The endpoints that read them are documented in API Specification.

payday

One row per user, overwritten on each recompute. prediction_date is the validity key: a row is served only while it matches the current UTC day; the TTL is garbage collection only.

Attribute Description

prediction_date

UTC day (YYYY-MM-DD) the row was computed on; must equal today to be served

detection_used

Winning algorithm: PAVE_PAYDAY_CALCULATION, FLOATME_V2_PAYDAY_CALCULATION, or FLOATME_PAYDAY_CALCULATION

next_date, source, frequency, loan_id, created_date

The chosen prediction’s payday, income source name, and cadence, plus the requesting loan and write time

pave, fm, v2

Each algorithm’s full prediction (payday, cadence, instant, standard, and extended collection dates); pave and v2 are null when the chain short-circuited

Source: pkg/dynamo/payday.go

income_verification

One row per user: txn_name, txn_id, amount_in_cents, pay_frequency, institution_id, verification_status (pending, approved, denied), is_valid, last_updated, notes[], verification_source (ollie, mx, or empty). Source: pkg/dynamo/income_verification.go

balance

One row per user per calendar month: accounts[] (account_id, amount, subtype), total_available, updated_date. The API reads the current month and the two before it. Source: pkg/dynamo/balance.go

alert

alert_sent, updated_date, balance_setting, available_balance, current_balance; updated_date drives the 7-day cooldown. Source: pkg/dynamo/alert.go

site-incomedetection

Written by the API Lambda on every income detection run; nothing in this service reads it.

Key Value

PK

INCOME_DETECTION#<user_id>

SK

<run_date> (RFC3339)

TTL

7 days

Attributes

method_a_results through method_ml_results (detected transactions per method), ml_enabled, ml_results_used, ml_prediction_id, ml_predictions, ml_probabilities, run_date

Source: pkg/dynamo/income_detection.go

site-fmdatacapture

Shared cross-service analytics capture table; the Insight Service only writes to it, through the fmsdk/clients/datacapture client. Every row has a 2-day TTL.

Event name SK Payload

PAYDAY_PREDICTION

Assigned by the fmsdk datacapture client

Every algorithm’s prediction and error, detection_used, used_v2, used_pave_v2, from_cache, loan_id, prediction_date; written on every evaluation, cache hit or miss

FM_PAYDAY_FILTERED_TXNS

FM_PAYDAY_FILTERED_TXNS#<date>

Payroll-candidate transactions selected by FloatMe V2; one row per user per day

FM_PAYDAY_PREDICTED_PAYDAY

FM_PAYDAY_PREDICTED_PAYDAY#<date>

FloatMe V2 predicted payday and cadence; one row per user per day

Source: pkg/payday/helpers.go, pkg/payday/floatme_predictor.go

user-balance-settings

Owned by another service; read by balance-alert. Key user_id; attribute low_balance_alert (dollars; null means alerts are off). Source: pkg/floatme/setting.go

locks

Shared distributed-lock table driven by cirello.io/dynamolock. Balance-alert takes one lock per user, key balance-alert:user_id:<user_id>, with a 60-second lease and 1-second heartbeat, and releases it when the message finishes. Source: pkg/dynamo/lock.go