Projects

Our own WMS on top of pick-to-light

Order and stock management depended on a vendor's software. I moved it into our ERP, and it has been live since March 2026.

Details

Year January – March 2026, improved ever since
Outcome 90% faster order prep, 99.9% of orders fulfilled
Tools Python, Flask, PostgreSQL, SQLAlchemy, Socket.IO, Redis, APScheduler

How it works

  1. 1 Shopify the order arrives by webhook, verified with HMAC
  2. 2 Pre-allocation stock reserved first come, first served, with priorities
  3. 3 Buffer five orders always ready for the shuttle
  4. 4 Pick-to-light aisle lights guide the picker
  5. 5 Validation every bottle scanned: GS1-128, DataMatrix, SGTIN-96
  6. 6 Dispatch label and Shopify fulfillment, no manual steps

Context

The company picks orders in its warehouse with a third-party pick-to-light system: aisles with lights, a shuttle and totes. Physical picking worked well, but order management, stock and production needs lived in the vendor’s software. In 2025 monthly orders grew more than sixfold, and every change we needed took weeks.

What I did

I moved all of that logic into our Flask and PostgreSQL ERP. Orders arrive from Shopify by webhook and a pre-allocation step reserves stock first come, first served, with priority for pickups and urgent orders. The system always keeps five orders ready for the shuttle and switches the lights on through the vendor’s API; if that API stops responding, it cuts itself off and raises an alert.

At validation every bottle is scanned, the box is chosen and the label and Shopify fulfillment happen with no extra steps. Stock and locations are now ours, with an aisle map you can edit in the app, and every movement is logged.

Before going live I tested it with 150 end-to-end test orders and a suite that simulated 20,000.

Outcome

Live since 25 March 2026. Since then it has handled hundreds of thousands of orders, with 99.9% fulfilled. Average order-prep time fell by 90% between 2025 and 2026, and the company stopped paying the vendor for every change.

What I learned

The real problems showed up with volume. First, double reservations caused by concurrency, solved with a per-order lock. Then a promotion with thousands of pending orders slowed everything down; I fixed it that weekend with multiple workers, Redis locks and sticky sessions, and since then I design for the peak, not the average.