Overview
Redesign the pool investment workflow so concurrent investors cannot oversubscribe a vehicle, spend the same wallet balance twice, or leave partially updated funding totals.
Problem
Vehicle and loan funding totals are denormalized, while investment records and wallet balances are stored separately. Two requests arriving at the same time can both observe available capacity and balance, then commit conflicting updates. This can create negative balances, overfunded vehicles, duplicate investments, or mismatched totals.
Scope
- Introduce an explicit investment command/service with MongoDB transaction boundaries.
- Add reservation states such as
pending, reserved, settled, expired, cancelled, and failed.
- Atomically validate investor balance, remaining pool capacity, pool/vehicle status, KYC eligibility, and amount limits.
- Reserve capacity and funds using conditional updates or versioned documents.
- Settle the reservation into an active investment and ledger/transaction records.
- Release expired or failed reservations safely.
- Add an idempotency key for retries from the frontend or API client.
- Recompute or verify
totalFunded, fundingProgress, and related cached values.
- Fix the mismatch between the
Investment TypeScript status union and schema enum.
Concurrency requirements
- Two requests for the final available amount must result in only one successful settlement.
- Retried requests with the same idempotency key return the original result.
- A failed database operation must roll back wallet, reservation, investment, and funding-total changes.
- Reservation expiry must not release funds already settled.
Suggested files
- investment API routes
models/Investment.ts
models/Vehicle.ts
models/Loan.ts
models/User.ts
lib/services/investment.service.ts
- background reservation-expiry worker
Test requirements
- parallel requests against the last pool capacity
- duplicate idempotency keys
- insufficient balance under concurrency
- transaction rollback after an injected failure
- reservation expiry and release
- pool status changes during reservation
- invariant checks for total investments versus funded totals
Acceptance criteria
Evidence required
- Automated test running at least 20 parallel investment attempts
- Output showing no negative wallet balance or overfunded pool
- State-transition diagram or contributor documentation
Difficulty
Hard
Overview
Redesign the pool investment workflow so concurrent investors cannot oversubscribe a vehicle, spend the same wallet balance twice, or leave partially updated funding totals.
Problem
Vehicle and loan funding totals are denormalized, while investment records and wallet balances are stored separately. Two requests arriving at the same time can both observe available capacity and balance, then commit conflicting updates. This can create negative balances, overfunded vehicles, duplicate investments, or mismatched totals.
Scope
pending,reserved,settled,expired,cancelled, andfailed.totalFunded,fundingProgress, and related cached values.InvestmentTypeScript status union and schema enum.Concurrency requirements
Suggested files
models/Investment.tsmodels/Vehicle.tsmodels/Loan.tsmodels/User.tslib/services/investment.service.tsTest requirements
Acceptance criteria
Evidence required
Difficulty
Hard