Linnworks Specialist · Case Study

Linnworks couldn’t reorder.
So we built the engine it was missing.

Linnworks is a capable order & warehouse system — but as a re-order tool it leans on static, hand-typed min/max levels. For a 10,000-SKU battery distributor, that meant overstock and stockouts at the same time. Here's how we replaced its reorder logic with a demand-driven engine that actually explains itself.

£0
Live stock value managed
£0
Open POs tracked
0
SKUs flagged for review
0%
Stock value from a real PO
The Challenge

An order system with reorder stapled on

The root failure is simple: in Linnworks, reorder points are static, manually-maintained min/max levels per SKU. Every suggestion is only as good as the number a human last typed — and those go stale the moment demand shifts. Everything else cascades from that one architectural choice.

“Once a suggestion needs full manual verification before you can action it, it isn't a suggestion — it's just a list.”

Open-PO blindness

Reorders against on-hand, not on-hand + on-order. Stock already in flight on a live PO doesn’t suppress a fresh suggestion — so you double-order. Clean, repeatable, expensive.

No defence against spikes

One big trade order inflates a SKU’s run-rate and Linnworks treats it as steady demand — over-ordering for weeks off a single lumpy line, with nothing to flag the number is unsafe.

No MOQ awareness

Suggests “order 37” when the supplier ships in 24s. Every figure needs hand-correcting against pack sizes and minimums before it becomes a real PO.

No explainability

Every suggestion is a black box of static thresholds with no derivation. Staff can’t sanity-check it — which quietly destroys trust in the whole feature.

The twin consequence: overstock on slow movers (cash tied up, shelves full) and stockouts on fast movers (lost sales, panic POs) — happening simultaneously, because the levels driving both were typed in once and forgotten.

The Solution

A reorder screen that shows its working

Instead of a black box, every line carries its derivation and a confidence rating, so the lowest-confidence lines surface first for review. Below-MOQ lines are flagged for a one-click bump, and stock already on a PO is counted before anything new is raised. The headline change isn't the maths — it's that a buyer can read why.

Velorai reorder and purchasing screen
Click to enlarge
Under the Hood

The two-formula engine

Each SKU is routed by a Just-In-Time flag. Supply is common to both: Supply = Stock + Due — where Due (on-order) is the exact open-PO fix Linnworks lacked.

// JIT products — don't hold stock, just cover committed demand
Order = MAX(0, Open Orders + Effective Min − Supply)

// Non-JIT products — forecast-driven
Lead Demand  = Lead Time × Daily Average
Cycle Demand = Order Cycle × Daily Average   (if cycle ordering on)
Order = MAX(0, Open Orders + Lead Demand + Cycle Demand + Effective Min − Supply)

A near-zero forecast collapses to “cover committed demand only”, and the quantity is computed once per canonical SKU so renamed variants never double-count. Below-MOQ lines are flagged for a one-click bump — surfaced for the buyer, not silently rounded.

The Smart Layer

Every line knows how much to trust itself

Each suggestion is scored against the active velocity window (not lifetime sales) on three tests: how many distinct order lines it has, whether one order is more than 80% of the window's demand (a lumpy spike), and whether it's gone stale (>45 days since the last sale). The result is a four-level confidence rating, so a buyer trusts the High bulk at a glance and reviews the handful that scored Low.

High
10+ order lines, steady
trust & approve
Medium
3–9 lines in window
moderate history
Low
<3 lines, spike >80%, or stale
flag for review
None
no sales in window
not recommended
Live distribution across 2,224 actively-selling SKUs (production):
High 817
Med 356
Low 1,051

Nearly half score Low — the exact lines Linnworks would have actioned blind. The engine routes them to a human instead.

Architecture

Linnworks stays the source of truth

A deliberate boundary: the integration is read-heavy by design. A wrong write to a live warehouse system is expensive and hard to unwind; a bad read just makes a suggestion you can ignore. So Linnworks remains the system of record, and the tooling is read-only intelligence on top.

LinnworksSync + WorkerSupabaseWeb appBuyer
Pull: a scheduled Apps Script sync plus a credential-safe Cloudflare Worker — stock, open orders, sales velocity.
Gotchas: dynamic server URL, an 18-hour session token, 150 req/min with back-off, all form-encoded.
Write-back: minimal and gated. Approvals and overrides live in the app's own database — nothing silently writes to Linnworks.
Valuation & Margin

The right cost, with a paper trail

Linnworks' single cost field is the root of bad reorder economics and bad margin. The replacement is a best-available-cost priority chain — a replacement-cost basis that answers “what would it cost to restock this today”.

permanent_zeromanual_costlatest PO costSage last-buymaster Excelnone → review

In practice the chain resolves cleanly: 76% of live stock value is costed straight from a real purchase order, 16% from Sage, and the rest from manual or Excel fallbacks — with only 30 in-stock SKUs left flagged for review. And it self-heals: fix a wrong cost in Linnworks and it corrects on the next sync.

Before & After

From a list you re-check to a tool you action

BeforeAfter

Linnworks reorder

Static, hand-typed min/max levels
Reorders against on-hand — double-orders stock already on a PO
Fixed lead times, no safety stock
Raw quantities, ignores MOQ & pack sizes
One lumpy order skews demand for weeks
Black box: re-verify every line by hand
Engineering Honesty

Where forecasting still needs a human

No forecast is perfect. A single large trade order can still inflate a SKU's run-rate and skew its suggested quantity — the same failure mode we levelled at Linnworks. Outlier-trimming the raw daily-rate is the next refinement on the list.

The difference is the engine knows when to doubt itself. That skew doesn't pass silently — it drops the line's confidence to Low, so it surfaces for review before a buyer approves it. The engine runs automatically on auto-synced Linnworks data; the human stays in the loop exactly where judgement is needed.

Running Linnworks and fighting your reorder?

If your min/max levels are typed in and forgotten, there's a better way — built on top of the Linnworks you already run, without betting the warehouse on automated writes. Let's talk.

Book a free discovery call