Warehouse Automation · 2025 · Addverb Technologies

Maersk · Adidas — Warehouse Automation Platform

A multi-tenant Warehouse Execution & Control System (WES/WCS) for the Maersk-operated Adidas distribution centre — orchestrating 12+ Spring Boot microservices that run the entire inbound-to-outbound flow: decanting, storage, picking, auction-based order allocation, robotic-arm induction, packing, returns and dispatch.

RoleSoftware Development Engineer
Timeline2025
TeamCross-functional (Backend, QA, DevOps, Product)
Scale12+ services · 10K+ events/min · 99.8% uptime

Problem

Maersk — operating the Adidas DC — needed a single, multi-tenant automation platform that could orchestrate heterogeneous subsystems (conveyors, AMRs, robotic arms, GTP stations, packing lines) behind a unified API and SSO. The existing stack was partly monolithic, hard to deploy per-site, and lacked cross-service observability for irregular events that blocked throughput SLAs.

My Contribution

Tech Stack

High-Level Design (HLD)

flowchart LR
  UI["Adidas Frontend (React)"] --> GW["API Gateway / SSO"]
  GW --> WES["WES
(Warehouse Execution)"] WES --> AUC["Auction
Service"] WES --> DEC["Decanting"] WES --> PCK["Packing"] WES --> RET["Returns"] WES --> RA["Robotic Arm"] WES --> BOX["BoxIt
(Location Strategy)"] WES --> MPR["Multipro"] WES --> QDR["Quadron"] WES --> OUT["Outbound"] WES --> VEL["Veloce"] subgraph MB["Message Bus"] RMQ[(RabbitMQ)] end AUC --- RMQ DEC --- RMQ PCK --- RMQ RET --- RMQ RA --- RMQ BOX --- RMQ MPR --- RMQ QDR --- RMQ OUT --- RMQ RMQ --> EVT["Event Store
(MongoDB)"] WES --> DB[(MySQL / MSSQL)] EVT --> OBS["Grafana + Jaeger
Dashboards"]
Design rationale: every subsystem owns its own DB and contract; cross-service side-effects flow through RabbitMQ topics so services fail independently. A parallel event-store in MongoDB gives operators a second "source of truth" for irregular events without touching transactional stores.

Low-Level Design — Order Fulfilment Flow

sequenceDiagram
  autonumber
  participant U as Operator (UI)
  participant G as SSO + Gateway
  participant W as WES
  participant A as Auction
  participant B as BoxIt
  participant R as Robotic Arm
  participant P as Packing
  participant Q as RabbitMQ
  participant M as MongoDB Event Store

  U->>G: POST /orders (JWT)
  G->>W: createOrder()
  W->>A: allocate(order)
  A-->>W: allocation plan
  W->>Q: publish order.allocated
  Q->>B: consume → pick slot
  B->>R: trigger induction
  R-->>Q: publish arm.completed
  Q->>P: consume → pack
  P-->>Q: publish pack.completed
  Q->>M: persist lifecycle events
  W-->>U: order status (WS / poll)
                

Impact

Key Learnings