VegMove
Grocery shopping, warehouse picking and delivery, connected through one backend.
Used by For customers, warehouse teams, packers, drivers and administrators.
A grocery order passes through several hands before it reaches the customer. VegMove connects those steps: shopping on the web or phone, picking stock from a shelf, packing the order and handing it over for delivery.
The backend uses NestJS and PostgreSQL, with Next.js interfaces and Flutter apps around it. The engineering gets interesting where those workflows meet: keeping inventory consistent, making reports traceable and handling work that needs to happen later.
- Context
- Company project, Techsfera
- Backend
- NestJS REST APIs, Prisma and PostgreSQL
- Clients
- Next.js storefront and administration; Flutter apps
- Live updates
- Server-sent events over Redis subscriptions
- Background work
- BullMQ order tasks, delay alerts and notification schedules
Keeping stock consistent
A retried stock movement needs to be recognized before it changes the balance again. The inventory code checks the request’s idempotency key, takes a row lock, then checks the key once more. The movement record and balance update happen in the same transaction.
Transfers lock shelf locations in a consistent order to reduce deadlock risk. Returns have their own placement rules, taking the warehouse, existing stock and cabinet access into account. The destination matters as much as the quantity.
Reports and work that happens later
Reporting stays close to the data. PostgreSQL handles filtering, aggregation and pagination using CTEs, window functions and lateral joins. Customer cohort reports also let an operator look beyond a summary and see the customers behind it.
BullMQ handles order follow-up tasks, payment timeouts, delivery-delay alerts and scheduled notifications. Jobs get identifiers tied to the task or record they concern, and notification schedules are also stored in PostgreSQL.
Connecting the customer and operations screens
The storefront updates the cart immediately while a request is running. If it fails, TanStack Query restores the previous cart. The admin console shares date-range, filter and column-visibility utilities, while the Flutter warehouse app handles shelf selection and inventory requests.
Order updates reach clients through server-sent events backed by Redis subscriptions. Sign-in includes TOTP, encrypted secrets, CAPTCHA checks and Redis-backed attempt controls. Access to customer phone numbers is checked on the server and expires with the grant.