Reimagining B2B Demand Aggregation
Oodlestack is designed to solve the complexity of group buying. It’s not just an e-commerce app; it’s a coordination engine that aggregates demand from multiple buyers to unlock wholesale pricing tiers, using an operations-research allocation engine underneath rather than simple first-come-first-served logic.
It’s also a second iteration: the group-buying model started as CureCollective, my 2024 healthcare pooling prototype. Oodlestack rebuilds that idea with the hard parts done properly — constraint solving, concurrency safety, and settlement integrity.
The challenge was building a system that felt like a native mobile app but lived on the web, with correctness-critical allocation logic that has to hold up under concurrent orders.
The Architecture: Business Logic Lives in Postgres
I migrated the entire codebase from Provider to Riverpod, adopting HookConsumerWidget to combine Riverpod’s global state with Flutter Hooks’ local lifecycle management, and Freezed for immutable models throughout — a deliberate, documented choice to keep state changes predictable as the feature set grows.
The more consequential architectural decision was where business logic lives: demand aggregation, seller matching, and settlement calculations run as Postgres functions and triggers rather than JavaScript Edge Functions, so data processing happens where the data already is instead of round-tripping to a separate compute layer. Seller matching itself is a weighted scoring function (pricing 40%, distance 30% via Haversine, rating 20%, stock 10%) implemented directly in SQL.
The Engineering: Correctness Under Concurrency
The hardest bugs in this system weren’t UI bugs — they were race conditions and constraint-enforcement gaps in the allocation engine (see Challenges & Solutions below). The fixes converged on the same pattern: explicit row-level locking (SELECT ... FOR UPDATE, and FOR UPDATE SKIP LOCKED for the credit ledger) to stop concurrent requests from over-reserving inventory or double-applying rewards, plus database-level uniqueness constraints so an idempotency bug can’t resurface silently even if the application-level guard is ever bypassed.
On the mobile side, Flutter Web can’t natively bridge to the Google Places Autocomplete session-token API, so location search calls into plain JavaScript functions defined on the host page via dart:js_util, with a conditional-import stub keeping the same code path working unmodified on mobile.
Impact & Features
Today, Oodlestack provides a coordinated experience for both community organizers and business buyers: a calendar-based view of buying cycles that dynamically prices based on aggregated volume, a mobile-first UI built for field use, and an allocation engine — Google OR-Tools’ CP-SAT solver — that runs the actual buyer/seller/tier matching as a constraint-satisfaction problem rather than a greedy heuristic.