DynamoDB Tables
The Insight Service reads and writes four DynamoDB tables. The primary table (prod-pave) uses a single-table design and holds all insight, score, alert, and verification entities. The other tables are either owned by the Insight Service or shared cross-service stores.
prod-pave — Primary Insight Table
All entities in this table share the same PK and SK string attributes. The DBType attribute stores the entity discriminator. Key construction uses utils.HashJoinPath(), which joins path segments with #.
Key Construction Reference
| Entity | PK | SK | TTL Field |
|---|---|---|---|
|
|
|
None |
|
|
|
|
|
|
|
|
|
|
|
None |
|
|
|
|
|
|
|
1 year (365 days) |
|
|
|
None |
|
|
|
None |
|
|
|
5 days |
|
|
|
|
|
|
|
None |
|
|
|
None |
Entity Descriptions
insights (mine metadata)
Written by the feeder for every Pave mining event. Tracks the mining request’s timestamp and request ID. Read by the miner to correlate incoming Pave webhook data.
recurring (recurring expenses/income)
Written in batch by the miner after a successful Pave mining run. Each row is one recurring transaction pattern (expense or income source) returned by Pave. The TTL is computed from the due date of the last recurrence plus a configured buffer (pave_expense_ttl, default 1 day). Old rows expire automatically; new rows are written fresh on each mining run.
ritual (ritual expenses)
Same lifecycle as recurring — written by the miner from Pave’s ritual expense results. A "ritual" in Pave’s model is a discretionary but regular spending pattern (e.g., a weekly coffee shop visit). TTL mirrors the recurring pattern.
income (income sources)
Written by the miner. Stores the raw Pave income source list for the user. Unlike recurring and ritual, there is only one row per user (the SK ends in #<user_id>) so newer writes overwrite the previous row.
scores (cash advance scores)
Written by the miner after calling Pave’s cash-advance score API. Each score row is timestamped; the TTL defaults to 30 days (pave_score_ttl). The API Lambda reads the most recent score for GET /{user_id}/scores/cash_advance without calling Pave directly.
alert (balance alert state)
Written by the balance-alert Lambda after dispatching a notification. Tracks UpdatedDate (timestamp of last alert) and Sent status. Read before sending any alert to enforce the 7-day cooldown.
pave_label (feeder mining trigger)
Written by the feeder to mark that a user’s Pave insight mining has been scheduled. The presence of this row gates mining — the feeder does not re-queue a user who already has an active label. Read by the feeder on each Kinesis event.
last_page (mining pagination state)
Written by the feeder to record that a given Pave request ID represents the last page of an upload batch. TTL is 5 days. When the miner processes a job, it checks whether this entity exists for the {user_id, request_id} pair; if it does, the miner emits the user_new_insights_available EventBridge event.
cc_income_notification (credit card funds dedup)
Written by the funds-notifier after sending a credit card funds push notification. Prevents duplicate notifications within the buffer window. Queried by PK prefix to check if a notification was already sent recently. TTL defaults to 2 days (cc_notification_buffer_days).
income_verification (manual income verification)
Written by the income verification flow (manual entry + optional MX/Ollie provider augmentation). Deleted by the institution-change-handler when a user connects a new bank. Stores employer name, salary, pay frequency, and start date.
payday (payday prediction result)
Written by the payday predictor during float creation (when loan_id is non-empty). Stores the winning prediction and all collection date variants (instant, standard, extended) from both the Pave and FM Legacy algorithms. The SK encodes the predicted next payday date for ordering — records with past dates are filtered out at query time (the query uses SK >= EXPIRES#<today>) but no TTL is set; records are not auto-deleted and are superseded by the latest write for a given user.
prod-incomedetection — Income Detection Results
| Field | Value |
|---|---|
Table name |
|
PK |
|
SK |
|
TTL |
7 days |
Written by the API Lambda after each income detection run. Stores the transaction set and detection method results for offline analysis. One record per user per day; older records expire after 7 days.
fmdatacapture — Cross-Service Data Capture
| Field | Value |
|---|---|
Table name |
|
Owner |
Shared cross-service table (Insight Service is a producer, not the owner) |
The Insight Service writes several data-capture record types to this table:
| Event Name | SK Pattern | Description |
|---|---|---|
|
|
FloatMe-generated forecasts written alongside Pave results for comparison. TTL: 2 days. |
|
|
Full payday prediction payload: all three algorithm results, all errors, |
|
|
List of payroll-candidate transactions used by the V2 payday algorithm. One record per user per day. TTL: 2 days. |
|
|
V2 predicted payday date and cadence. One record per user per day. TTL: 2 days. |
Legacy Tables (us-east-1)
These tables are owned by other services and accessed read-only (or with minimal writes) by the Insight Service.
| Table Name | Region | Used By |
|---|---|---|
|
us-east-1 |
Balance-alert Lambda reads each user’s configured low-balance threshold ( |
|
us-east-1 |
Balance-alert Lambda acquires a per-user distributed lock before processing each account event, to prevent duplicate alerts in concurrent SQS batches. |
Related Pages
-
Architecture — DynamoDB table list and access pattern overview
-
Pave Mining — Which entities are written during mining runs
-
Income Detection —
cc_income_notificationdedup andprod-incomedetectionwrite -
Balance Alerts —
alertentity read/write and legacy table access -
Cash-Advance Scores —
scoresentity lifecycle -
Forecasts & Payday —
paydayentity andfmdatacapturewrites -
Institution Changes —
income_verificationentity deletion