Case study · Warehouse systems

Four warehouses, one stock figure, and no oversell

A multi-site distributor managed stock in one spreadsheet per warehouse, reconciled by phone, which produced regular oversell and an annual stocktake that closed each site for three days. We built a real-time stock ledger with offline-capable handheld scanning, lot and serial traceability, and a nightly reconciliation against the ERP. Stock accuracy now sits above 99 per cent and the annual shutdown stocktake has been replaced by weekly cycle counts.

Client · Multi-site distributor Sector · Wholesale & distribution Engagement · Discovery, build, rollout, support Duration · Eleven months including rollout Status · Live at all four sites Delivery model · Incremental build, staged go-live

Each warehouse kept its own workbook. Quantities were typed in at the end of a shift, adjusted by whoever was on the fork lift, and reconciled with head office by telephone when a discrepancy was noticed — usually after a customer had been told an item was available and it was not. There was no lot or serial record at all, so a product recall meant reading invoices backwards to work out which customers might have received an affected batch. Goods receipt was recorded on paper at the dock and keyed hours later, sometimes the next morning, which meant the numbers always trailed the physical warehouse.

We delivered a stock ledger and the mobile application that writes to it. Every movement — receipt, put-away, pick, pack, transfer, adjustment, count correction — is appended as an immutable line, and available quantity is derived rather than stored, so a figure can always be explained down to the scan that produced it. Receiving, picking, packing and counting run on the client's existing Android handhelds and continue to work where there is no wireless coverage, queueing scans locally and replaying them in order when the device reconnects. Transfers between sites, reorder suggestions and freight consignment booking are handled in the same system, and the whole ledger is reconciled against the ERP every night.

Engagement facts

Warehouse sites4 (WA and SA)
Active SKUs21,400
Movements per week~46,000
Handheld scanners62 existing Android units
Offline toleranceValidated to 8 hours
ERP reconciliationNightly, 0.1% drift alert
Freight integrationBooking, label, tracking
RolloutOne site every three weeks
SupportAWST business hours + on-call

01The problem

Oversell was routine rather than exceptional. Because each site's workbook was updated at the end of a shift, two sites could both sell the last of a line within an hour of each other, and the discovery happened at pick time when the picker could not find the stock. Sales would then call the customer, offer a substitute, or split the order and back-order part of it. The distributor logged 34 such events in the quarter before we started, and each one cost an apology, a freight concession or a lost line.

Traceability did not exist. Without lot or serial capture the business could not answer which customers received a given batch, could not isolate stock to a single site during a quality hold, and could not support a supplier claim with evidence. Cycle counting was an annual event: each warehouse shut for three days, staff counted bin by bin on paper, and the resulting corrections were keyed in weeks later, by which time the numbers had moved again. Purchasing was decided from a report generated weekly from the ERP, which was itself fed by the same delayed figures.

  • One spreadsheet per site, updated at shift end
  • Concurrent sales of the same stock from different warehouses
  • No lot or serial record for any product line
  • Goods receipt keyed hours after the pallet landed
  • Annual full shutdown stocktake, corrections applied weeks later
  • Purchasing decisions based on week-old figures

02Constraints and non-negotiables

The handheld scanners were not ours to replace. Sixty-two Android units had been bought two years earlier, were configured for warehouse use with gloves and cold rooms in mind, and the client's position was that any solution had to run on that hardware or the business case disappeared. That fixed the mobile platform and the form factor: large touch targets, readable in bright yard light, usable one-handed.

Coverage was the second hard constraint. Wireless signal in the cold storage rooms was unreliable to the point of being unusable, and the freezers were not going to be re-surveyed mid-project, so scanning had to work with no connection and reconcile later. Permissions were strictly per site: a Perth picker should never see another site's stock or costs, while two head office roles needed a consolidated view. The ERP remained the financial system of record, so the new system had to agree with it rather than replace it. And the client had one absolute rule: available quantity must never go negative, because negative stock had previously been used to paper over late receipting and had destroyed trust in every report built on it.

  • Existing Android handheld scanners retained, no hardware spend
  • Cold storage rooms with unusable wireless coverage
  • Freight provider API as the only booking channel
  • Per-site permissions with a consolidated head office view
  • Negative stock prohibited in every circumstance
  • ERP retained as the financial system of record

03What we built

The core is a movement ledger. Nothing updates a quantity in place; instead each event appends a line carrying site, SKU, lot or serial where applicable, quantity, direction, reason, device, user and timestamp. Available stock is computed from those lines and cached as a materialised balance for speed, with the ledger remaining authoritative. The practical effect is that a stock figure can be traced: if a balance looks wrong, the movements that produced it are listed underneath it rather than guessed at.

On top of the ledger sit four working applications. The handheld app covers receiving against purchase orders, put-away with directed bins, pick by wave or by order, pack with carton confirmation, and ad-hoc cycle counts, all of which queue locally when offline. A web console shows live stock by site and bin, manages transfers between warehouses with dispatch and receipt confirmation, and raises reorder suggestions from actual consumption rather than last week's export. A freight integration books consignments and prints labels through the provider's API. An ERP connector posts receipts, issues and adjustments and runs the nightly reconciliation.

04The hard parts and how we solved them

Modelling stock as an append-only ledger rather than a mutable quantity changed almost every downstream decision. The immediate cost is that reads become aggregations, so we maintain a materialised balance per site, SKU and lot, updated transactionally in the same database transaction as the movement, with a nightly job that recomputes balances from the ledger and compares them. That comparison has never been the interesting part; the interesting part is that a discrepancy now produces a report instead of an argument.

Offline writes arriving out of order was the problem we spent longest on. A device can be offline for hours, and two devices can scan the same pallet in different rooms, so arrival order at the server is not event order. Each scan carries a device-generated identifier and a device clock time, and the ledger accepts them idempotently, but ordering is resolved server-side against a per-site sequence with a reconciliation rule for the case where a later scan arrives first. Where the resolved order would push a balance below zero, the movement is held for review rather than applied — the client's no-negative-stock rule is enforced at write time, not reported afterwards.

Cold storage was addressed by treating those rooms as permanently offline rather than intermittently connected: scans are written to device storage, shown to the operator as confirmed locally, and synchronised when the device reaches coverage, with a dock-side checkpoint that refuses to close a transfer until every scan has landed. Volume was the last issue. A small number of fast-moving SKUs accounted for a large share of movements and produced lock contention on the balance rows; we batched movements within a transaction, moved the balance update to an increment rather than a recalculation, and partitioned the ledger by month, which held median write latency under 40 milliseconds at peak.

05Cutover and change management

We went live one site at a time, three weeks apart, starting with the smallest warehouse. Each site began with a full physical count loaded as the ledger's opening balance, which gave the system a defensible starting position and gave the site a clean number to trust. For the first two weeks at each site the old workbook was maintained in parallel, and every evening the two were compared; once a site had passed ten consecutive clean comparisons, the workbook was frozen and archived.

Training was done on the floor, not in a room. Operators practiced receiving and picking on real orders with the system open alongside the old process, and the two staff at each site who picked the system up fastest became the local reference points named in the support rota. Freight booking was switched last, after the ledger had settled, because it was the only part of the workflow where a mistake was immediately visible to a customer.

06Results, and what we would do differently

Stock accuracy, measured as lines where the ledger agrees with a physical count, moved from 87.4 per cent at baseline to 99.2 per cent and has stayed there for four consecutive quarters. Oversell events have not occurred in the twelve months since the last site went live, against 34 in the quarter before the project began. Cycle counting now runs weekly by zone instead of annually by shutdown, and a zone count takes just over two hours with the warehouse open, against three closed days for a full site count. Reorder suggestions are generated from consumption recorded the same day.

The thing that went wrong appeared at the first month-end reconciliation. We had modelled transfers between sites as two movements — an issue at origin and a receipt at destination — and treated the gap between them as belonging to the origin site. In practice goods spent up to two days in transit, so the ledger showed stock at origin that was physically on a truck, and the reconciliation reported 0.4 per cent drift concentrated entirely in transfer lines. The fix was to add an in-transit state to the ledger rather than to adjust the numbers: a dispatched transfer creates an in-transit holding that belongs to neither site's available quantity, and the destination receipt clears it. Drift on transfer lines fell to zero the following month.

What we would do differently concerns the handheld software rollout. We distributed the first builds by manual install, which was fine for a pilot and slow for sixty-two devices; a managed device enrolment from the start would have saved a week per site. We would also have built the in-transit state into the first data model, because we knew transfers existed and treated them as an edge case when they were not.

99.2%
Stock accuracy, was 87.4%
0
Oversell events in twelve months
52
Cycle counts a year, was one
2.1 hrs
Per zone count, was three closed days
Warehouse supervisor reviewing stock figures on a desktop console
The annual stocktake used to cost us three days per site and we still did not believe the numbers. Now a count is something we do on a Tuesday afternoon, and when a figure looks wrong the system shows us the scans behind it.
Warehouse Operations Manager, multi-site distributor
Delivery notes

Stack and delivery notes

The service runs in containers behind a managed PostgreSQL instance in the Sydney region, with a message broker carrying freight and ERP work so that a slow downstream system cannot block a scan. Dashboards show reconciliation drift, offline queue depth per device and write latency.

Python FastAPI PostgreSQL Redis RabbitMQ Flutter Android handheld scanners Docker Terraform AWS Grafana Power BI
Related work

Other delivered systems

Most of our work starts with a number somebody does not trust. These case studies describe that number, what was causing it, and what changed. Request a quote if you would rather talk about your own operation first.

Field Service Operations Platform

Job capture and asset history for mobile crews working where connectivity is not guaranteed.

ERP & CRM Integration Hub

One governed integration layer replacing fourteen connectors, with drift reporting between systems.

Client Self-Service Portal

Ordering, documents and approval routing delivered over an existing ERP rather than around it.

Legacy Platform Cloud Migration

A fifteen-year-old application rehosted to AWS in four stages with a tested restore.

Not confident in your stock figures?

A 45-minute scoping call, no obligation. We will tell you honestly whether a ledger rebuild is warranted.

Request a Quote