The client buys luxury watches from auctions around the world. Each acquisition needs to be photographed, background-removed, quality-checked, and uploaded to their product system before it can be listed for sale. With 1,500+ images per week, the manual process had become the bottleneck.
- 3-day backlog between photo and live listing: watches sat in inventory without generating revenue
- Inconsistent background removal quality across different operators
- Manual S3 upload process prone to errors and naming inconsistencies
- Staff time consumed by repetitive, low-value image processing tasks
- Listing delays directly impacted cash flow on acquired inventory
- Python ML worker detects the watch subject and removes background automatically
- Image resized, optimized, and formatted to product listing specifications
- Direct upload to AWS S3 with correct naming convention and folder structure
- React dashboard for queue monitoring, success/failure tracking, and manual override on edge cases
- Node.js orchestration manages the queue, retries failed jobs, handles batch processing
The Python / Node.js split was intentional and worth explaining. Python owns the ML inference layer: background removal, subject detection, image quality scoring. Node.js owns orchestration: queue management, retry logic, S3 naming conventions, job state. We deliberately separated these concerns because they evolve at different rates. The ML model will be swapped or upgraded independently of the pipeline logic; the S3 naming convention will change independently of the ML model. Coupling them in a single runtime would have made every change riskier. The React dashboard exists not as a control panel but as an exception interface: operators should only see images that failed automated processing. Designing the dashboard around the exception case rather than the normal case kept the team honest about automation quality: if operators were spending significant time in the dashboard, the automation was not good enough.
The pipeline eliminated the 3-day backlog entirely. Watches sourced on Monday are listed by Monday afternoon.
The 80% cost reduction came from replacing per-image manual labor with automated processing. The React dashboard gives operators visibility without requiring them to touch every image.
The hardest part of this project was not the ML integration. It was defining what "good enough" meant for background removal on luxury watch photography. Auction photos come in under fluorescent lights, on velvet trays, against inconsistent backgrounds. Early pipeline runs had an 8–12% manual review rate. The client pushed us to get it below 3%. That pressure led us to add a confidence scoring layer on top of the background removal model: images below a threshold were automatically flagged before reaching the operator queue rather than passing through and wasting review time. Confidence scoring added two weeks of engineering but halved the manual review rate. The lesson: ML quality gates are not a product feature. They are part of the model deployment strategy.


