Overview
Blnk’s lineage system tracks fund provenance by creating shadow balances that maintain separate accounting for each fund source (provider). When money moves between balances, the lineage follows, ensuring complete traceability. Key Concepts:- Provider: The source/origin of funds (e.g., “stripe”, “bank_transfer”, “loan”)
- Shadow Balance: Hidden balance tracking a specific provider’s funds
- Aggregate Balance: Sum of all shadow balances for an identity
- Lineage Mapping: Association between main balance, provider, and shadow balances
Architecture
The lineage system (implemented in/lineage.go) uses a shadow balance architecture:
Shadow Balance Naming
Shadow balances use indicator-based naming (lineage.go:288-308):- Shadow:
@{provider}_{firstname}_{lastname}_{id_prefix}_lineage - Aggregate:
@{firstname}_{lastname}_{id_prefix}_lineage
Enabling Lineage Tracking
On Balance Creation
Enable lineage tracking when creating a balance:track_fund_lineage: Enable lineage tracking (default: false)allocation_strategy: How to allocate funds on debit (FIFO, LIFO, PROPORTIONAL)identity_id: Required for lineage tracking (used to generate shadow balance names)
Recording Transactions with Lineage
Credit (Incoming Funds)
Specify the fund provider when crediting a balance:- Main transaction:
@world → bal_alice_usd($1000) - Shadow transaction:
@stripe_alice_xyz_lineage → @alice_xyz_lineage($1000) - Lineage mapping created linking provider to shadow balance
Debit (Outgoing Funds)
When debiting a balance with lineage, funds are allocated from shadow balances:- Main transaction:
bal_alice_usd → bal_bob_usd($600) - Allocation (based on strategy):
- If FIFO and Alice has 600 from Bank:
- Release $400 from Stripe shadow
- Release $200 from Bank shadow
- If FIFO and Alice has 600 from Bank:
- Shadow release transactions created
- If Bob also tracks lineage, receive transactions created
- Metadata updated with fund allocation breakdown
Allocation Strategies
When debiting a balance, funds are allocated from shadow balances using one of three strategies:FIFO (First In, First Out)
Allocate from the oldest funds first:- Regulatory compliance requiring oldest funds spent first
- Inventory accounting
- Default strategy
LIFO (Last In, First Out)
Allocate from the newest funds first:- Tax optimization
- Prefer spending recent deposits
Proportional
Allocate proportionally across all sources:- Fair distribution across sources
- Risk spreading
- Regulatory requirements for balanced allocation
Querying Lineage
Balance Lineage
Get fund breakdown for a balance:Transaction Lineage
Get fund allocation for a transaction:Use Cases
1. Regulatory Compliance
Scenario: Track loan funds separately from customer deposits2. Anti-Money Laundering (AML)
Scenario: Trace funds through multiple hops3. Escrow Services
Scenario: Track buyer funds vs platform feesPerformance Considerations
Locking Strategy
Lineage uses multi-lock acquisition to prevent race conditions (lineage.go:505-521):- Sorts lock keys to prevent deadlocks
- Deduplicates lock keys
- Uses Redis distributed locks
- Separate namespace from main transaction locks
Batch Optimization
Shadow balances are fetched in a single query to reduce database round trips (lineage.go:837-874):Transaction Impact
Lineage adds overhead per transaction: Credit Transaction:- Main transaction: 1
- Shadow transaction: 1
- Lineage mapping insert: 1
- Total: 3 database operations
- Main transaction: 1
- Shadow release transactions: N (one per provider allocated)
- Shadow receive transactions: N (if destination tracks lineage)
- Metadata update: 1
- Total: 2 + 2N database operations
- Use lineage only where compliance requires it
- Limit number of providers per balance (< 10)
- Use appropriate allocation strategy (FIFO is fastest)
- Consider batch processing for bulk transfers
Best Practices
- Enable Lineage at Balance Creation: Cannot be enabled retroactively
-
Use Meaningful Provider Names: Easy to audit
-
Consistent Provider Naming: Use standardized format
-
Set Identity ID: Required for lineage tracking
-
Choose Appropriate Strategy: Based on compliance needs
- FIFO: Most regulatory scenarios
- LIFO: Tax optimization
- Proportional: Risk distribution
-
Monitor Shadow Balances: Set up alerts for discrepancies
Troubleshooting
Lineage Not Tracking
Symptom: Transactions processed but no lineage data Solutions:- Verify
track_fund_lineageenabled on balance - Check
identity_idis set on balance - Ensure provider specified in
meta_data.BLNK_LINEAGE_PROVIDER - Check logs for lineage processing errors
Balance Mismatch
Symptom: Main balance ≠ sum of shadow balances Diagnosis:- Check for failed shadow transactions
- Review outbox for pending lineage work
- Manually reconcile discrepancies
- Contact support if persistent
Provider Validation Failed
Symptom:- Verify provider exists:
GET /balances/{id}/lineage - Check provider name spelling
- Ensure funds were credited with that provider