Architecture
System Overview
The LOC Service is built as a collection of AWS Lambda functions that work together to provide installment loan functionality. The service uses DynamoDB as its primary data store with a single-table design pattern.
┌─────────────────────────────────────┐
│ External Services │
│ ┌─────────┐ ┌─────────┐ ┌────────┐ │
│ │ Users │ │Payments │ │Iterable│ │
│ │ Service │ │ Service │ │ API │ │
│ └────┬────┘ └───┬─────┘ └──┬─────┘ │
└───────┼──────────┼──────────┼───────┘
│ │ │
┌─────────────────────────────────────┼──────────┼──────────┼──────────────┐
│ LOC Service │
│ │ │ │ │
│ ┌──────────────┐ ┌────┴──────────┴──────────┴─────┐ │
│ │ API Gateway │◄────────────►│ API Lambda │ │
│ └──────────────┘ │ (Applications, Loans, etc.) │ │
│ └───────────────┬────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────┼─────────────────────┐ │
│ │ DynamoDB │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ │
│ │ │ Loans │ │Installmts│ │ Payments │ │ LoanApps │ │ Logs │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └─────────┘ │ │
│ └───────────────────────────────┬───────────────────────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ DynamoDB Stream │ │
│ └────────┬────────┘ │
│ ┌─────────────┼─────────────┐ │
│ ▼ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │Log Handler │ │ Expiration │ │ Other │ │
│ │ (Audit) │ │ Handler │ │ Handlers │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Collections System │ │
│ │ ┌─────────────┐ ┌─────────┐ ┌─────────────┐ │ │
│ │ │ CloudWatch │───►│ Job │───►│ SQS Queue │ │ │
│ │ │ Events │ │ Lambda │ │ │ │ │
│ │ └─────────────┘ └─────────┘ └──────┬──────┘ │ │
│ │ │ │ │
│ │ ┌───────▼─────┐ │ │
│ │ │ Worker │ │ │
│ │ │ Lambda │ │ │
│ │ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ACH Webhook Handler │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Kinesis │───►│ ACH Handler │ │ │
│ │ │ Stream │ │ Lambda │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘
Lambda Functions
API Lambda (cmd/api)
The main REST API handling all loan operations:
-
Loan Applications - Create, approve, reject applications
-
Loan Creation - Disburse funds and create loan records
-
Loan Queries - Get loan details, installments, payments
-
Manual Payments - User-initiated loan payments
-
QA Endpoints - Testing and development utilities
Collections Job (cmd/loc-collections-job)
Scheduled Lambda that runs collection processes. See Collections for details.
Collections Worker (cmd/loc-collections-worker)
SQS-triggered Lambda that processes payment events from the collections queue.
ACH Handler (cmd/ach-handler)
Kinesis-triggered Lambda that processes payment webhooks:
-
ACH returns and completions
-
Pinless debit chargebacks
-
Payment status updates
Expiration Handler (cmd/expiration-handler)
DynamoDB Stream-triggered Lambda that handles TTL expirations:
-
Marks expired loan applications as
ABANDONED -
Cleans up orphaned records
Agreements Generator (cmd/agreements-generator)
SQS/Direct-invoke Lambda that generates loan agreement PDFs. See Loan Agreements for details.
Payment and Collections Flow
The collections system handles automated payment processing through scheduled jobs:
Collection Processes
| Process | Description | Creates Payments | Sends Notifications |
|---|---|---|---|
|
Notifies users of payments coming due |
No |
Yes |
|
Processes installments due today (autopay or notify) |
Yes (autopay) |
Yes (non-autopay) |
|
Notifies users of past-due installments |
No |
Yes (scheduled) |
|
Retries failed payments |
Yes |
No |
Daily Schedule
| Time (CST) | Process | Description |
|---|---|---|
5:00 AM |
|
Retry failed payments |
7:00 AM |
|
Process today’s installments |
8:00 AM |
|
Notify of payments in 3 days |
9:00 AM |
|
Notify of overdue payments |
For detailed collection system documentation, see Collections.
Payment Flow
User Payment Request Autopay Collection
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ API Lambda │ │ Collections │
│ POST /payback │ │ Job │
└───────┬───────┘ └───────┬───────┘
│ │
│ ┌──────▼──────┐
│ │ SQS Queue │
│ └──────┬──────┘
│ │
│ ┌──────▼──────┐
│ │ Worker │
│ └──────┬──────┘
│ │
└───────────────┬───────────────┘
│
┌───────▼───────┐
│ Engine │
│ (Payback) │
└───────┬───────┘
│
┌───────▼───────┐
│ Payments │
│ Service │
└───────┬───────┘
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Success │ │ Retry │ │ Failed │
└──────────┘ └──────────┘ └──────────┘
DynamoDB Design
The service uses a single-table design with composite keys. See the Data Model documentation for details on each entity.
Key Prefixes
| Prefix | Entity |
|---|---|
|
User identifier |
|
Loan record |
|
Loan application |
|
Payment record |
|
Installment record |
|
Payment audit log |
|
Installment audit log |
Global Secondary Indexes
The table uses 4 GSIs for different access patterns:
-
GSI1 - Status-based queries (loans by status, installments by status)
-
GSI2 - Cross-user queries (all payments, all installments by date)
-
GSI3 - Lookup by external ID (confirmation ID, application ID)
-
GSI4 - Reserved for future use