Part 1 — The Business of Fashion Wholesale
J Warehouse, Logistics and Fulfillment Operations
Everything your ERP records eventually happens to a physical box in a physical building, moved by a person who is paid by the hour and measured by the minute. This chapter walks the goods from the moment a container backs onto your dock to the moment a customer sends half of it back. Where a number is solid, it is cited. Where the industry genuinely varies, it is given as a range and labeled as one. If you build software for this world without understanding it, you will build screens nobody can use while wearing gloves.
In this chapter
- What you need to know first
- The flow of goods, end to end
- Warehouse layout and slotting
- Picking methods compared
- Inventory accuracy
- 3PL versus in-house
- Value-added services
- Freight and transport
- Customs and import mechanics at the operational level
- Returns operations
- Peak season and labor
- Metrics for the operation
- What this means for your ERP
What you need to know first
A warehouse is a building where you keep goods you own but have not yet sold or shipped. A distribution center (DC) is the same building described by people who want to emphasize that goods move through it quickly rather than sit. A fulfillment center is the same building again, described by people who ship mostly single items to consumers. Do not read too much into the words. What matters is the physics: goods arrive in big units, get broken into smaller units, and leave in the size the customer wants.
The two customer types drive everything. Wholesale means you sell to a retailer — a department store, a boutique, an online retailer — who then resells to shoppers. Wholesale orders are big, arrive weeks in advance, and ship as cartons (cardboard boxes) on pallets (a wooden platform, typically 48″×40″ in the US, that a forklift can lift).
DTC means direct-to-consumer: you sell from your own website to one person, and you ship one or two garments in a poly mailer (a soft plastic envelope). Chapter B introduced these as sales channels. Here they are two different factories that happen to share a roof.
The words you will hear every day
Some vocabulary you need before the rest of this chapter makes sense. None of it is hard, but all of it gets used every day by people who will assume you already know it.
A SKU (stock keeping unit, pronounced "skew") is the smallest thing you can count and sell. In apparel a SKU is style + color + size. "Ridge Jacket, Olive, Medium" is one SKU. "Ridge Jacket" is a style and is not countable, because you cannot ship a style. A single style in 4 colors and 6 sizes is 24 SKUs. This multiplication is the central operational fact of apparel: a modest 60-style range is well over a thousand SKUs, each needing its own place on a shelf.
An each is one single unit — one garment. Warehouse people say "eaches" to distinguish single garments from cartons and pallets. Breaking a carton open to get at the individual garments inside is called breaking to eaches.
A bin location (or just "location") is an addressable place in the building where inventory sits — a shelf, a section of a shelf, a floor position, a pallet slot. Every unit in a well-run warehouse is in a named location, and the name is printed as a barcode on the rack.
Purchase orders, EDI and the ASN
A purchase order (PO) is your order to your factory. Chapter B called this procure-to-pay. EDI (electronic data interchange) is the decades-old standard for sending business documents computer-to-computer instead of by email; each document type has a number, so people say "an 856" the way you would say "an invoice."
An ASN (advance ship notice, which is EDI document 856) is the electronic message a supplier sends saying "here is exactly what is on the truck, packed into exactly these cartons, arriving on this date." An ASN turns receiving from a counting exercise into a scanning exercise. That is far faster, because you scan one label per carton instead of counting every garment inside it.
The six warehouse verbs
- Receiving is unloading and verifying inbound goods.
- Put-away is moving them from the dock to their storage location.
- Picking is retrieving units to satisfy an order.
- Packing is putting picked units into the box that will travel.
- Staging is parking finished shipments near the door in the order they will be loaded.
- Ship confirm is the software step that says "this left the building," which is the moment the goods stop being your inventory and start being either a receivable or a delivery obligation.
WMS, available-to-sell, RMAs and 3PLs
A WMS (warehouse management system) is the software that runs the inside of the building: locations, tasks, scanners, waves, labels. Some ERPs include one. Most do not, and you either buy one or write the parts you need. When this chapter says "your ERP must," read it as "your ERP or the WMS it talks to must."
ATS means available-to-sell: the quantity your sales team and website are allowed to promise. It is not the same as the quantity in the building. Goods sitting in a quality-check hold are physically present but not available to sell. Chapter 8 covers how to calculate and cache this number; this chapter covers all the physical states that must be excluded from it.
An RMA (return merchandise authorization) is the reference number you give a customer so that when their parcel comes back you know whose order it was. Returns without an RMA are the expensive kind.
A 3PL (third-party logistics provider) is a company that operates a warehouse on your behalf. You send them goods, they store, pick, pack and ship, and they invoice you per activity. The alternative is in-house: you lease a building, hire people, and do it yourself.
Wholesale dates and floor-ready delivery
Wholesale orders carry dates, and the dates have names:
- The start ship date is the earliest day the retailer will accept the goods.
- The cancel date is the last day; miss it and the retailer may legally refuse the whole order.
- Some retailers instead give you a MABD — a must arrive by date, meaning the goods have to be physically at their door by then. Handing them to a carrier on that date does not count.
The difference matters a great deal, because MABD makes transit time your problem. Floor-ready means the goods arrive at the retailer in a state where a store employee can put them straight onto the sales floor: correct hanger, correct price ticket, correct security tag, no repacking needed.
Transport words: parcel, LTL, FTL, ocean and air
On the transport side:
- parcel means small packages moved by UPS, FedEx, USPS or a regional carrier.
- LTL (less-than-truckload) means a few pallets sharing a trailer with other shippers' freight.
- FTL (full truckload) means you buy the whole trailer.
- Ocean means a shipping container on a vessel; air is the same goods in a plane, far faster and far dearer.
- Cube is the volume a shipment occupies, in cubic feet — carriers care about it as much as they care about weight.
- Drayage is the short truck move from the port to your warehouse.
- A BOL (bill of lading) is the legal document that says who handed what freight to which carrier, signed at the moment of pickup.
- Prepaid means you pay the freight; collect means the receiving retailer pays it and therefore chooses the carrier.
At the border: brokers, bonds and the tariff schedule
At the border, a customs broker is the licensed agent who files your import paperwork with US Customs and Border Protection (CBP), and a customs bond is the guarantee that CBP gets paid if you do not pay. HTS is the Harmonized Tariff Schedule, the numbered catalog that assigns every importable product a code and a duty rate.
Shrinkage and the numbers people quote
Finally, shrinkage (or "shrink") is inventory that the system says you have but the shelf does not. It has several causes running at once: theft, mis-picks, receiving errors, damage nobody logged, and units that were counted into the wrong bin.
The National Retail Federation's National Retail Security Survey put the retail industry average at 1.6% of sales in fiscal 2022, which was $112.1 billion. The 2025 Warehousing and Fulfillment Costs & Pricing Survey — an annual poll of 600-plus warehouse and 3PL operators, published as the 2025 Warehousing Market Report — reported a self-declared average shrinkage rate of 2.68% among providers.
Treat both as order-of-magnitude signals. They are self-reported, they are measured against completely different denominators, and any individual operation can sit far outside them. Both are the latest editions verified as of July 2026; check for newer ones before you quote them.
The warehouse is the only place in your business where the database can be wrong in a way you can walk over and look at. Every other module argues about interpretation. This one has a ground truth, and your job as the ERP builder is to make the distance between the record and the ground truth small, visible, and cheap to close.
The flow of goods, end to end
Follow one container of a spring delivery from the factory to the customer. Every step below is a place your software either helps or gets in the way.
Inbound appointment
Warehouses have a fixed number of dock doors and a fixed number of people who can unload. If four containers show up at 9am unannounced, three wait, and the trucking company charges you for the waiting.
So inbound freight is booked into a dock appointment: a time slot at a specific door, requested by the carrier or freight forwarder and confirmed by the warehouse. The appointment carries a reference, usually the container number or the PO number, and that reference is how the warehouse knows what to expect. If your ERP cannot answer "what PO is on container MSKU1234567" at 6am when the driver calls, someone loses an hour.
Receiving and verification against the ASN and PO
The container is opened and unloaded. Apparel arrives one of two ways. Floor-loaded means cartons are stacked loose from floor to ceiling to maximize container use; a 40-foot container commonly holds several hundred to well over a thousand apparel cartons this way, depending on carton size, and unloading it by hand takes two people several hours.
Palletized means cartons arrive already stacked on pallets; a forklift empties the container in well under an hour, but you fit meaningfully fewer cartons in, because the pallets themselves eat space. Floor-loading trades ocean freight cost for domestic labor cost, and which is cheaper flips with the market.
Verification is a three-way comparison: what the PO said you ordered, what the ASN said the supplier shipped, and what actually came off the truck. The ASN is the pivot. A good ASN is hierarchical — shipment contains pallets, pallets contain cartons, cartons contain SKUs and quantities, and each carton carries a label with a globally unique SSCC.
SSCC stands for Serial Shipping Container Code, and in plain language it is a license plate for one physical box: an 18-digit number, issued by you, that identifies that specific carton and nothing else in the world. It is printed as a GS1-128 barcode, a format built to carry several separate pieces of logistics data in one symbol.
It uses Application Identifiers — short numeric prefixes that tell the scanner what the data after them means:
- AI (00) means "an SSCC follows."
- AI (02) means "the GTIN of the trade items inside follows," where a GTIN is the 14-digit global product number behind a retail barcode.
- AI (37) means "and here is how many of them are in this carton."
RECEIVING A CONTAINER: THE THREE-WAY MATCH
PO 4471 ASN (EDI 856) PHYSICAL
--------- ------------- ---------
RIDGE-OLV-S 120 carton 001..004 scanned 4 ctns
RIDGE-OLV-M 240 carton 005..012 scanned 8 ctns
RIDGE-OLV-L 240 carton 013..020 scanned 7 ctns <-- short
RIDGE-OLV-XL 120 carton 021..024 scanned 4 ctns
--------------- --------------
24 cartons 23 cartons
Carton 018 label (GS1-128, human readable):
(00) 0 0614141 123456789 0 <-- SSCC, AI 00, 18 digits
(02) 1 0614141 00015 6 <-- GTIN of contents, 14
(37) 30 <-- 30 units in carton
RESULT
Expected 720 units / Received 690 units
Variance -30 units on RIDGE-OLV-L, one carton not on truck
Action: receive 690, raise inbound discrepancy on PO 4471,
do NOT silently amend the PO quantity
Read that from the top. The PO is your commercial intent: 720 jackets across four sizes. The ASN is the supplier's declaration, broken down to the carton, with each carton given an SSCC so it is uniquely identifiable anywhere in the world. The physical count is what the receiver actually scanned. One carton of size L is missing.
The correct behavior is to record what actually arrived (690), raise a discrepancy against the PO, and leave the PO at 720 so the gap stays visible to whoever must chase the supplier or the carrier. The tempting shortcut, editing the PO down to 690 so everything "balances", destroys the only evidence that anything went wrong.
Notice too that with SSCC-labeled cartons and a matching ASN, receiving 24 cartons takes 24 scans instead of 720 hand counts. That is why retailers penalize suppliers who send bad ASNs, and why you should demand ASNs from your own factories just as insistently.
Quality check
Receiving proves the count. QC (quality control) proves the goods are sellable. In apparel this is not optional: a garment factory's third production run can differ from the approved sample in color, measurement, stitching or labeling, and you will not find out at the port.
Practical QC at receipt uses a statistical sample rather than a full inspection. The standard method is AQL sampling. AQL stands for Acceptable Quality Limit, and the underlying standard is ANSI/ASQ Z1.4, the US national standard for sampling by attributes. "By attributes" just means you count how many sampled units pass or fail, rather than measuring anything.
The idea is simple even though the tables look intimidating. You look up your shipment size in a table, and the table tells you how many units to pull and inspect. You also choose an AQL number, 2.5 is common in apparel, which means "I will still accept this shipment if up to 2.5% of units are defective." The table converts that into a plain accept/reject count.
At AQL 2.5, a sample of 80 units is accepted at 5 or fewer defects and rejected at 6. That is the whole mechanism. Look up your own lot size rather than reusing those numbers. Bigger shipments get bigger samples, but not proportionally bigger, which is why sampling is cheap.
What you check on each sampled garment:
- measurements against the spec sheet
- color against the approved lab dip (the small swatch of fabric the mill dyed and you signed off as the correct color)
- care and content labels
- country-of-origin marking
- hangtags and price tickets
- and that the retail barcode scans to the right SKU.
A failed sample escalates to a wider inspection or a full hold.
The labeling checks exist because US law requires them. Country-of-origin marking has to appear on the article itself, fiber content and care instructions are regulated by the Federal Trade Commission, and children's apparel carries additional Consumer Product Safety Commission requirements. A container that arrives with the wrong care label cannot ship to a department store. It has to be re-labeled, which is a service you pay for by the unit.
Goods that have been counted but not yet QC-passed are physically in your building and must not be sellable. If your ERP moves inventory straight from "received" to "available," your sales team will sell a container that is about to be rejected. Model QC hold as a location or a status that the available-to-sell calculation excludes, and connect it to the ATS logic from chapter 8.
Put-away and storage strategy
Put-away moves goods from the receiving dock into storage. There are three broad strategies:
- Fixed location means every SKU has one permanent home. Easy for humans to learn, terrible for space: a SKU with zero stock still occupies its shelf.
- Random (chaotic) location means the system assigns whatever empty location is nearest and records it; space use is excellent, but the operation now depends entirely on the software being right.
- Hybrid is what almost everyone actually runs: fast-moving SKUs get fixed pick faces (a small, permanently assigned shelf position at floor or waist height that pickers visit), and everything else goes into random reserve storage — usually full pallets up high.
Apparel has a specific wrinkle: goods are stored either flat (folded in cartons or on shelves) or GOH (garment on hanger, hung from rails). GOH costs far more per unit of storage but eliminates pressing later, so it is used for tailored clothing, outerwear and anything that creases badly. A building that must do both needs two different storage geometries and two different picking motions.
Replenishment of pick faces
A pick face holds a few dozen units. A reserve pallet holds hundreds. Replenishment is the task of moving stock down from reserve into the pick face before it runs empty. It is the single most under-appreciated warehouse process, because when it fails, picking stops, and picking stopping is the expensive thing.
Replenishment is triggered by a min/max rule per location: when on-hand in the pick face falls below the minimum, generate a task to bring it back to maximum. Good systems run replenishment ahead of the wave, using the demand in the wave to predict which faces will empty. Bad systems run it reactively, so pickers discover empty faces one at a time and log short-picks that are not really short.
Picking, packing, staging, loading, ship confirm
Picking is covered in depth below. After picking, packing puts units into the outbound container: a carton for wholesale, a poly mailer or small box for DTC.
Wholesale packing is governed by the retailer's routing guide — the vendor manual that specifies carton dimensions, maximum weight, label placement, how many SKUs may share a carton, and whether cartons must be packed by store. Getting this wrong produces a chargeback: the retailer deducts a penalty from your invoice, usually without asking first.
Packed cartons get a carton label with an SSCC and, for retail, the retailer-specified content. Staging parks the finished shipment in a marked floor area by carrier and by departure time. Loading puts it on the trailer, usually in reverse delivery order so the first stop is nearest the door. Ship confirm closes the loop: tracking numbers are captured, the ASN goes to the retailer, the invoice can be raised, and the inventory ledger records the outbound movement.
OUTBOUND TIMELINE, ONE WHOLESALE ORDER
D-14 Order released from ERP; allocation reserves units
D-7 Routing request sent to retailer's traffic desk
(weight, cube, carton count, ready date)
D-4 Routing instructions returned: carrier assigned,
tracking reference and pickup date issued
D-3 Wave released to floor; replenishment tasks run first
D-2 Pick -> QC -> ticket/hang extra services -> pack
D-1 Cartons labelled (SSCC), palletised, staged by door 12
D-0 09:00 carrier arrives, BOL signed, trailer loaded
11:20 SHIP CONFIRM in the WMS
11:21 EDI 856 advance ship notice sent to retailer
11:22 EDI 810 invoice queued (terms start on ship date)
11:23 inventory ledger: -690 units, location OUT
Miss the routing request window and the retailer assigns
no carrier. The order sits. The cancel date passes.
Study the timeline above, because it shows how much of "shipping" happens before anything is picked. On collect freight terms, the retailer, not you, chooses the carrier, and they choose it from the data you submit in a routing request roughly a week out. That request needs accurate weight and cube, which means your ERP needs carton dimensions and weights per SKU long before the goods are packed.
The last three lines — advance ship notice, invoice, ledger — all fire off the same ship-confirm event, which is why that event must be idempotent (chapter 3) and must never half-succeed. "Idempotent" here just means: run it twice by accident and nothing doubles.
Warehouse layout and slotting
Zones and the bin location naming scheme
A location code is an address. Like a street address, it should be readable by a human under pressure, sortable by a machine, and unambiguous. The near-universal convention is a fixed-width, hierarchical code.
LOCATION CODE ANATOMY
A - 12 - 03 - B
| | | |
| | | +-- LEVEL (A = floor, B = 2nd, C = 3rd...)
| | +------- BAY (position along the aisle, 01-99)
| +------------ AISLE (01-99)
+----------------- ZONE (A = pick, B = reserve, C = GOH,
R = returns, Q = QC hold,
D = damage, S = staging)
Printed on the rack as: A-12-03-B
Barcoded as: A120 3B (no separators, fixed width)
SORT ORDER = PICK PATH
A-01-01-A -> A-01-02-A -> A-01-03-A -> A-02-08-A ...
Sorting the code ascending walks the picker down aisle 1,
then up aisle 2. No thinking required.
SERPENTINE VARIANT (avoids walking back to the aisle head)
odd aisles sort ascending, even aisles descending:
A-01-01 .. A-01-20, A-02-20 .. A-02-01, A-03-01 ..
The critical property is in the last two blocks. Because the code is fixed-width and hierarchical, sorting a pick list by location code in ascending order produces a walking route through the building. You get route optimization for free from an ORDER BY. If your codes are variable-width (A-1-3-B next to A-12-3-B) the string sort puts aisle 12 before aisle 2, and your picker zig-zags. If your codes embed no zone, you cannot ask "show me everything in QC hold." If you allow free-text location names ("back corner by the fan") you have no sortable route at all.
Why slotting by velocity matters
Slotting is deciding which SKU lives in which location. Most of the time in picking is spent walking. In a manual operation where people walk to the goods, travel routinely accounts for around half of a picker's paid hours, and studies and vendor benchmarks put it anywhere from roughly a third to two-thirds depending on building size and order profile. Whatever the exact share, it is the biggest single block of time. So the highest-velocity SKUs belong closest to the packing stations and at the most ergonomic height.
The golden zone is the shelf band between roughly knee and shoulder height where a picker can grab without bending or reaching. Putting your top sellers there and your slow movers on the top and bottom shelves costs nothing and permanently removes seconds from thousands of picks.
SLOTTING MATH: WHAT SECONDS ARE WORTH
(illustrative, but the arithmetic is the point)
Assumptions (mid-size apparel DTC operation)
orders/day 1,200
average lines (SKUs) per order 2.4
picks/day 2,880
working days/year 255
picks/year 734,400
fully-loaded labour rate $26.00/hr (wage + burden)
Save 4 seconds per pick by re-slotting the top 200 SKUs
into the golden zone near packing:
734,400 picks x 4 s = 2,937,600 s = 816 hours/year
816 h x $26.00 = $21,216/year
Save 15 seconds per pick because half your fast movers sit
in the far aisle on the top shelf and need a ladder:
734,400 x 15 s = 3,060 hours = $79,560/year
Neither number appears on any invoice. Both are real.
The arithmetic is worth doing slowly. A mid-size operation does about three-quarters of a million picks a year. At that scale, four seconds is 816 hours — roughly half a full-time employee. Fifteen seconds is nearly two full-time employees, paid every year, to compensate for a shelving decision somebody made in an afternoon. ("Fully loaded" means the wage plus everything that rides on it: payroll taxes, workers' compensation insurance, benefits and paid time off. "Burden" is the industry word for that extra.)
This is the silent cost of a bad location scheme. No line item on any report carries it. It surfaces instead as needing more headcount than your peers to ship the same volume.
Slotting is not set-and-forget. Apparel velocity changes with the season, so a fast mover in March is dead stock in September. A practical cadence is a full re-slot twice a year at season change, plus a monthly pass that moves the top 50 movers into the golden zone. The data you need is the pick count per SKU per location over the last N weeks, which your ERP already has if you log picks properly.
One refinement: pure velocity slotting fights a second effect. Apparel orders are correlated within a style, so slotting all sizes of a style adjacently turns four separate walks into one stop with four grabs. The working rule is "slot by velocity at the style level, keep the size run contiguous."
Picking methods compared
There are five methods you will meet. They are not ranked; each fits a different order profile — the statistical shape of your orders, chiefly lines per order, units per line, and orders per day.
| Method | How it works | Best order profile | Weakness |
|---|---|---|---|
| Discrete / order picking | One picker walks the whole building for one order, start to finish | Low volume, many lines per order, high-value or bespoke; also small wholesale operations | Maximum travel per unit. Does not scale past a few hundred orders a day |
| Batch picking | One picker carries a cart of totes (plastic bins, one per order) and picks 10–30 orders in one trip, dropping each unit into the right tote as they go | High volume, 1–3 lines per order — the classic DTC profile | Sortation errors; picker must place each unit in the right tote. Needs cart discipline |
| Zone picking | Building divided into zones; each picker only works their zone; order fragments meet later at consolidation | Large buildings, wide SKU spread, mixed storage types (flat plus GOH) | Requires a consolidation step and a way to detect incomplete orders. Adds cycle time |
| Wave picking | Orders grouped into a timed release ("wave") aligned to a carrier cut-off, the daily deadline after which a parcel ships tomorrow instead of today, or to a trailer departure | Any operation with hard departure times — almost all wholesale | Idle time between waves; a late wave cascades into a missed truck |
| Pick-and-pass | A tote moves along a conveyor or by hand through zones in sequence, each zone adding its lines | Many lines per order across many zones; steady, predictable volume | The slowest zone paces the whole line. Very sensitive to workload imbalance |
These combine. "Zone + batch + wave" is an extremely common real configuration: the building is split into zones, each zone picker batches several orders per trip, and the whole thing is released in waves timed to the 16:00 parcel trailer. Your ERP will need to represent all three concepts simultaneously.
Why wholesale cartons and DTC singles are genuinely different operations
This is the point most software gets wrong, so it deserves its own treatment. Consider two orders of the same 690 units.
SAME 690 UNITS, TWO OPERATIONS (illustrative)
WHOLESALE DTC
1 order 420 orders
690 units 690 units
4 SKUs ~180 SKUs touched
23 cartons out 420 poly mailers out
1 BOL, 1 ASN, 1 invoice 420 labels, 420 tracking #s
1 pick trip (full cartons) 420 picks + 420 packs
labour: a few hours labour: most of two shifts
packaging: 23 cartons packaging: 420 mailers
freight: 1 LTL shipment 420 parcels
cost/unit shipped: cents cost/unit shipped: dollars
ERROR PROFILE
wholesale: one mistake x 690 DTC: 420 chances at 1 mistake
-> a chargeback, maybe a -> a few angry customers,
whole rejected delivery a few return labels
TIMING PROFILE
wholesale: fixed window, DTC: same-day cut-off,
start ship / cancel date every single day
Read down the two columns. The wholesale side moves inventory in its native packaging: cartons come off a pallet, get labeled, and go back onto a pallet. Very little touches an individual garment. The DTC side must open cartons, break them into eaches, store the eaches somewhere pickable, and then handle each garment individually through pick, pack and label.
That is a completely different set of equipment (shelving versus racking), a different labor skill, a different consumable inventory, and a different daily rhythm. The per-unit cost gap is roughly an order of magnitude, which is why the two are priced separately on every 3PL rate card you will ever read.
Running both in one building is hard for four concrete reasons:
- First, they compete for the same people at the same time, and wholesale has hard immovable dates while DTC has a daily cut-off, so peak weeks force a choice.
- Second, they want different storage: wholesale wants full cartons on pallets, DTC wants eaches in bins, and the same SKU held in both forms is two inventory pools that must be reconciled and rebalanced.
- Third, the packing benches and consumables are different, so floor space allocated to one is unavailable to the other.
- Fourth, and least obvious, the performance metrics conflict: wholesale is measured on delivering complete and on time to a date, DTC on same-day dispatch, and a supervisor who is being graded on both will sacrifice whichever is measured less loudly.
Do not model "inventory at the warehouse." Model inventory at a location, and let locations carry a unit-of-measure and a channel affinity. A carton pick face and an each pick face for the same SKU are different rows with different quantities that happen to share a SKU. The moment you collapse them into one number, you lose the ability to answer "can I ship this wholesale order today" and "can I ship this DTC order today," which have different answers.
Inventory accuracy
Cycle counting programs
A cycle count is counting a small slice of the warehouse today, and a different slice tomorrow, so that over a period every location gets counted without ever stopping operations. It is the professional alternative to shutting the building for a weekend.
Cycle counts are almost always driven by ABC classification: rank SKUs by some measure of importance, usually annual pick frequency or annual cost of goods sold, and split them into classes. A common apparel split is A = top 20% of SKUs, which typically generate the large majority of movement, B = next 30%, C = bottom 50%. Then count each class at a different frequency. The exact split varies by business; measure yours rather than assuming.
ABC CYCLE COUNT PROGRAMME, 1,400-SKU APPAREL DC
(illustrative shape; measure your own distribution)
Class SKUs % of picks Counts/yr Location-counts/yr
----- ----- ---------- --------- ------------------
A 280 74% 12 3,360
B 420 21% 4 1,680
C 700 5% 1 700
----- ----- ---------- --------- ------------------
Total 1,400 100% 5,740
Working days/year 255
Location-counts per day 5,740/255 = 22.5
Minutes per count (scan, count, confirm) ~4
Daily counting labour 22.5 x 4 = 90 min
ONE counter, half a shift, five days a week, and every
fast-moving SKU is verified monthly.
TRIGGERED COUNTS (added on top, not scheduled)
- pick face reported empty but system shows qty > 0
- negative on-hand at any location
- short-pick logged against a location
- variance found in a neighbouring bin
- SKU on a customer complaint about wrong item shipped
The table shows why ABC works: a small minority of SKUs generate most of the activity, so counting those twelve times a year and the dead stock once a year gives you almost all the accuracy benefit for a fraction of the effort. Ninety minutes a day is a rounding error against payroll. Note the second block especially — triggered counts, generated by events rather than a schedule, catch errors within hours instead of weeks, and they are pure software: your ERP already knows when someone logged a short-pick.
The measure you are chasing is inventory record accuracy (IRA), normally computed as the percentage of counted locations where system quantity exactly equaled counted quantity. Note "exactly" and note "locations." Counting by location is much harsher than counting by SKU across the whole building, because two offsetting errors in two bins net to zero at the SKU level and look perfect. Location-level IRA is the number that predicts whether picking will go smoothly.
Full physical inventory
A full physical is counting everything, usually once a year, usually over a weekend, usually with the building frozen. Many businesses need one for their auditors. It is expensive, disruptive, and, done once a year by tired temporary staff, often less accurate than a well-run cycle count program. The realistic position: run cycle counting as your operational accuracy tool, and negotiate with your accountants to replace or shrink the annual full physical once you can show them a documented cycle count program with high measured IRA.
Shrinkage causes, honestly enumerated
People assume shrinkage is theft. In a wholesale apparel DC, theft is usually the smaller half. The realistic list, roughly in order of frequency:
- Receiving errors. Counted a carton as 30 when it held 24; scanned a carton twice; received against the wrong PO line.
- Put-away errors. Units physically placed in bin A-12-04 but recorded to A-12-03. The building-wide total still balances. Two individual bins are both wrong.
- Mis-picks. Picked size M when the order said S. Creates a negative in one SKU and a positive in another, plus a customer return later.
- Unrecorded damage. A carton gets crushed by a forklift and quietly binned. The unit exists in the system forever.
- Unrecorded samples. Sales pulls three jackets for a showroom appointment and tells nobody. In apparel this is chronic and it is always the fast-moving SKUs, which is why they are the ones that go negative.
- Theft. Internal and external. Real, but concentrated in high-value small items.
- Unit-of-measure confusion. A "case" of 12 recorded as 12 cases. Endemic where the same SKU is stocked in eaches, inner packs and master cartons.
Every one of these except theft is a software-addressable process failure, and most of them leave a trace your ERP could have caught.
Reconciling variances rather than adjusting them away
This is the discipline that separates a warehouse you can trust from one you cannot, and it ties directly to the append-only inventory ledger from chapter 1.
When a count says 24 and the system says 30, the lazy move is to write 24 into the on-hand field. The system now agrees with reality, the variance report shows nothing, and you have learned nothing. Do that a hundred times and you have a warehouse with a shrink number and no idea what is behind it.
The disciplined move is different. The count posts a ledger entry, and the entry carries a reason code, a reference to the count task, the counter's identity, the before and after quantities, and the delta. The on-hand quantity is then, as always, the sum of the ledger. Nothing is ever overwritten. And a variance above a threshold does not post at all until it has been investigated — recounted, checked against nearby bins, checked against recent picks and receipts, and assigned a root cause.
VARIANCE WORKFLOW (ledger-first, chapter 1 style)
1. COUNT TASK issued location A-12-03, SKU RIDGE-OLV-M
2. BLIND COUNT entered counter types 24 (system qty hidden)
3. SYSTEM COMPARES system 30, counted 24, delta -6
4. THRESHOLD CHECK |delta| x cost = 6 x $38 = $228
> $150 threshold -> INVESTIGATE
5. RECOUNT by second person confirms 24
6. INVESTIGATION
check A-12-04 found 6 units of RIDGE-OLV-M
root cause PUT_AWAY_MISLOCATION, receipt R-8891
7. RESOLUTION = TWO ledger entries, not one adjustment
ledger_entry 1
location A-12-03 sku RIDGE-OLV-M qty -6
reason COUNT_TRANSFER_OUT ref count_task 5512
ledger_entry 2
location A-12-04 sku RIDGE-OLV-M qty +6
reason COUNT_TRANSFER_IN ref count_task 5512
NET SHRINK RECORDED: ZERO. It was never missing.
8. IF no cause found after investigation
ledger_entry
location A-12-03 sku RIDGE-OLV-M qty -6
reason SHRINK_UNEXPLAINED ref count_task 5512
-> flows to the shrink report, which is now a report
about genuinely unexplained loss, not about sloppiness
Each numbered step buys something. Step 2, the blind count, hides the expected quantity from the counter — otherwise people confirm the number on the screen rather than count the shelf. Step 4 puts a value threshold on investigation so you do not spend $40 of labor chasing a $3 variance.
Steps 6 and 7 find that the units were never lost, only mislocated, and record the truth as a transfer. Step 8 is the honest fallback. The payoff is that your shrink report becomes meaningful: everything in it is genuinely unexplained, which means it is worth acting on. Under the lazy approach, the shrink report is mostly mislocated stock and is therefore ignored by everyone.
There should be no screen in your ERP with an editable "quantity on hand" field. Quantity on hand is derived. The only way to change it is to post a ledger entry with a reason code, and the set of reason codes should be a closed list you can report on. If someone with a database client can run UPDATE inventory SET qty = 24, your ledger is append-only in name only.
3PL versus in-house
The real decision criteria
Cost alone does not settle this. At low volume a 3PL is almost always cheaper, because you are renting a slice of someone else's fixed costs. At high volume in-house is almost always cheaper, because you stop paying someone else's margin — the 2025 Warehousing Market Report put the average 3PL profit margin at 9.27% on top of their costs. The crossover in apparel depends so heavily on your order profile that quoting a single volume would be dishonest. Model it for yourself; the exercise at the end of this chapter walks you through it.
The criteria that actually decide it:
- Volatility. Wholesale apparel is violently seasonal. A 3PL absorbs your peak with their other clients' troughs. In-house means you either carry the peak headcount all year or master temporary labor.
- Compliance complexity. If your retailers demand carton-level ASNs, store-ready ticketing and GOH, you need a partner who already does that. Building it yourself is a multi-year competence.
- Capital. Racking, conveyors, a WMS, a fleet of forklifts and a five-year lease are real money before you ship anything.
- Control and speed of change. With a 3PL, "add a new insert to every order" is a change order and a rate negotiation. In-house it is an afternoon's work.
- Geography. Multiple 3PL sites cut parcel zones and transit days without you leasing multiple buildings.
- Talent. Running a DC is a specific profession. If you cannot hire an experienced operations manager, do not run a DC.
How 3PLs price, and how to read a rate card
A 3PL rate card is a menu of activities. The figures below are the reported averages from the 2025 Warehousing and Fulfillment Costs & Pricing Survey, published as the 2025 Warehousing Market Report, which polls more than 600 warehouses each year. They were the current published figures as of July 2026, and the survey is reissued annually, so re-check it.
They are self-reported averages across every industry and every size of operation, so treat them as a sanity check on whether a quote is normal — not as a target, and not as a price you are entitled to. Apparel quotes commonly sit above these averages because apparel needs more hand-work per unit.
| Line item | What it charges for | 2025 reported average |
|---|---|---|
| Setup / onboarding | Account creation, writing the standard operating procedures, system configuration | $333 (51% of providers charge one) |
| Integration fee | Connecting your shopping cart or ERP to their system | $275 |
| Receiving — per pallet | Unload, count, verify, label, stow | $10.52 per pallet |
| Receiving — per container | Unloading a floor-loaded container by hand | $500 per container |
| Receiving — per SKU | Per distinct product on the receipt | $2.75 per SKU |
| Receiving — hourly | Anything non-standard | $45.67 per hour |
| Storage — pallet | Per pallet position per month | $20.17 |
| Storage — bin/shelf | Per bin per month (single garments for DTC) | $3.08 |
| Storage — cubic foot | Per cubic foot per month | $0.46 |
| Long-term storage surcharge | Penalty on stock that will not move | 48.6% of providers charge one, reported at roughly 30–50% of the standard storage rate |
| Pick-and-pack — B2C | One-item consumer order | $3.20 |
| Pick-and-pack — B2B | One-item wholesale order | $4.80 |
| Returns processing | Receive, inspect, decide what happens to it | $4.06 |
| Account management | Named contact, reporting, meetings | $102.88/month (35% of providers charge) |
| Monthly minimum | Floor you pay regardless of activity | $517 |
| Annual price increase | Standard escalation written into contracts | 3.57% per year |
A few lines in that table deserve a second look. The wholesale (B2B) pick-and-pack rate is exactly 50% higher than the consumer (B2C) rate, which reflects the extra compliance work per order — retailer labels, routing guides, carton rules. Nearly half of providers now impose a long-term storage surcharge, which matters a great deal to a wholesale brand carrying carryover stock: a 3PL's economics reward inventory that moves, and they will price you out of storing anything that does not.
The monthly minimum is the industry quietly declining its smallest clients. And the 3.57% average annual increase means your year-two rates are not your year-one rates, so model three years, not one.
Any published rate card has two important gaps. First, apparel-specific work — ticketing, hanging, polybagging, steaming — is almost never in the published averages, because most surveyed warehouses do not do it. You must get those quoted separately and in writing. Second, freight is not in the rate card at all. It is passed through, and it is usually bigger than everything else combined.
A worked cost comparison
Here is a like-for-like annual comparison for a fictional but realistic wholesale-led apparel brand: roughly $14M at wholesale, 60% wholesale / 40% DTC, shipping about 350 wholesale orders and 95,000 DTC orders a year. Every rate marked (survey) is a verified 2025 average; everything marked (assumed) is a plausible placeholder you must replace with your own quote.
ANNUAL COST COMPARISON (illustrative, US, 2026 assumptions)
VOLUME ASSUMPTIONS
DTC orders/year 95,000
Wholesale orders/year 350
Wholesale cartons/year 14,000
Inbound containers/year 18
Average pallet positions held 620
Returns processed/year (DTC @ 22%) 20,900
-------------------------------------------------------------
OPTION A: 3PL Annual
-------------------------------------------------------------
Receiving 18 containers x $500 (survey) $9,000
Storage 620 pallets x $20.17 (survey) x 12 $150,065
Pick&pack DTC 95,000 x $3.20 (survey) $304,000
+ extra unit 38,000 x $0.55 (assum) $20,900
Pick&pack B2B 14,000 cartons x $4.80 (survey) $67,200
Ticketing 210,000 units x $0.14 (assumed) $29,400
Returns 20,900 x $4.06 (survey) $84,854
Account mgmt $102.88 (survey) x 12 $1,235
Setup + integration (year 1 only, survey) $608
--------
3PL SERVICES SUBTOTAL $667,262
Parcel + LTL freight (pass-through, assumed) $522,000
========
OPTION A TOTAL $1,189,262
-------------------------------------------------------------
OPTION B: IN-HOUSE (all figures assumed; price your
own market, rents vary hugely) Annual
-------------------------------------------------------------
Building 42,000 sq ft x $8.31 (triple net) $349,020
Utilities, trash, maintenance $58,000
Direct labour 9 staff x 2,080 h x $26.00 loaded $486,720
Supervision 1 x $72,000 + 1 clerk x $52,000 $124,000
Ops manager $95,000
Temp labour, peak (14 wks x 5 heads) $72,800
WMS licence + support $48,000
Racking + handling equipment (5 yr) + forklifts $61,000
Consumables (cartons, mailers, tape, poly) $79,000
Insurance and workers' comp premium delta $31,000
--------
IN-HOUSE OPERATING SUBTOTAL $1,404,540
Parcel + LTL freight (own contracts, -8%) $480,240
========
OPTION B TOTAL $1,884,780
ONE-OFF: fit-out, racking capex, WMS setup $410,000
-------------------------------------------------------------
VERDICT AT THIS VOLUME
3PL is cheaper by ~$695k/yr and needs no capex.
Break-even moves toward in-house when DTC orders
roughly triple (fixed costs spread) OR when extra
services and compliance rework start exceeding
~25% of the 3PL bill.
-------------------------------------------------------------
Some notes on how to read this. "Triple net" means the rent excludes property taxes, insurance and maintenance, which you pay on top, so a quoted rent per square foot is never the full building cost. Industrial rents vary by a factor of three or more between markets, so treat the $8.31 figure as a placeholder and get a real quote for a real building.
The structural point survives whatever numbers you plug in. The 3PL side is almost entirely variable: if volume halves, the bill roughly halves, apart from storage and the monthly minimum. The in-house side is almost entirely fixed: the building, the managers and the WMS cost the same whether you ship 95,000 orders or 195,000. That asymmetry is the real decision, far more than the headline total. A brand with volatile or uncertain volume should pay the 3PL premium for optionality. A brand with a dependable base load is buying an annuity by going in-house.
Also note that freight is shown separately on both sides and is the single largest line. Whoever controls the carrier contracts controls the biggest number, which is why 96% of warehouses in the 2025 survey let clients ship on their own carrier accounts. If a 3PL insists you use their rates and will not show you the underlying carrier invoice, that is a margin you cannot see.
SLAs and the hidden costs
A 3PL contract without a service level agreement (SLA — a written, measurable promise about performance, with a consequence attached) is a wish.
The SLAs that matter, with the ranges you should expect to negotiate:
- same-day dispatch for orders received before an agreed cut-off (typically 95–99% of orders);
- dock-to-stock time, meaning receipt available to sell within 24–72 hours of arrival;
- pick accuracy (the 2025 survey average is 99.42%, so anything above that is above-market and should be priced as such);
- inventory record accuracy (99%+);
- and returns turnaround (typically 2–5 business days).
Each SLA needs a defined measurement method, a reporting cadence, and a consequence. Get in writing who pays for shipping, picking and inventory errors when the 3PL is at fault, including a definition of "at fault."
The hidden costs, in rough order of how often they surprise people:
- Storage creep. You are billed per pallet position, and a half-empty pallet costs the same as a full one. Slow-moving apparel silently occupies positions for years. Long-term storage surcharges make it worse.
- Special projects billed hourly. Anything not on the rate card lands at an hourly rate — the survey average for non-standard receiving work is $45.67 an hour, and project work is usually quoted around that level. A retailer changing its ticketing requirement mid-season is a special project.
- Rework. When a retailer rejects a delivery, someone unpacks and repacks it. That is hours, at hourly rates.
- Exit costs. Removing inventory from a 3PL is billed as picking. Moving hundreds of pallets out can cost five figures, and this is exactly when your relationship is bad.
- Annual escalators. Around 3.57% a year on average, and often a clause linking increases to the Consumer Price Index (the government's official inflation measure) that you did not read.
- Integration drift. Every time you change your ERP's outbound format, someone bills for the change.
Value-added services
VAS (value-added services) is the umbrella term for everything done to goods in the warehouse that is not simply store-and-ship. In apparel it is where retailer compliance work lands, and it is often the difference between a delivery being accepted and being charged back.
| Service | What it physically is | Why it exists |
|---|---|---|
| Ticketing | Attaching a price ticket or hangtag with a plastic barb or string | Retailers demand their own ticket format with their own retail price and barcode. Wrong ticket = rejected delivery |
| Re-ticketing / re-labeling | Removing and replacing tickets or care labels | Markdowns, a retailer changing price, a wrong-language care label, a mis-printed origin label |
| Poly-bagging | Sealing each garment in a clear plastic bag | Protects from dirt and moisture; many retailers require it, some now forbid it for sustainability reasons |
| Re-packing | Opening factory cartons and repacking to a different configuration | Retailer routing guides specify carton counts, weights and pack-by-store rules the factory did not follow |
| Kitting / bundling | Combining several SKUs into one saleable unit with its own barcode | Gift sets, multipacks, influencer boxes. Creates a new SKU that consumes component SKUs |
| GOH (garment on hanger) | Hanging garments on retailer-specified hangers, sized and sequenced | Floor-ready delivery: the store hangs the rail straight onto the shop floor with no extra work |
| Steaming / pressing | Removing creases with a steamer or a heated tunnel the garments pass through | Ocean-shipped folded garments arrive creased and photograph badly; essential on returns |
| Inspection | Unit-by-unit visual and measurement check | Vendor quality problems, grading returns, high-value goods |
| Security tagging | Applying EAS tags (the hard plastic anti-theft tags a store removes at the till) or RFID tags (chips that can be read wirelessly in bulk) | Retailer loss-prevention requirement, increasingly RFID so the retailer can count stock without touching it |
What VAS costs and how it is quoted
VAS is labor, and labor is priced by the hour or by the unit. Published survey averages barely cover apparel-specific work, so you will be quoted bespoke. Ticketing is usually quoted per unit and the price swings with the details: whether the ticket is pre-printed or must be printed on site, whether it is a quick plastic barb or a strung hangtag, and how much sorting the operator has to do first.
Get a per-unit quote in writing before you commit to a retailer's ticketing requirement, and do the multiplication yourself — a 22-cent ticket on a 210,000-unit season is $46,200 you did not budget. Hourly work (rework, re-packing, kitting) is commonly quoted in the same band as non-standard receiving, which the 2025 survey put at $45.67 an hour on average.
Why VAS is invisible in your accounts
In apparel, VAS is a substantial share of the fulfillment bill. It is driven entirely by what your customers demand rather than by anything you chose, and it is the part of the operation most likely to be invisible in your accounts. Large 3PLs increasingly build apparel-dedicated buildings precisely because hanging, tagging, ticketing and rework need different benches, different equipment and differently-trained people from picking boxes.
A "needs ticketing" true/false field on an order line collapses under the first real requirement. VAS is a job with an instruction set, a unit count, a labor standard, a cost, a start and end time, and possibly a different physical location. Give it its own table, link it to the order line and the inventory movement, and you can answer "what did compliance work cost us at Retailer X this season" — a question every wholesale brand eventually asks and almost none can answer.
Freight and transport
The four modes and how each is priced
Parcel is priced on billable weight and distance zone, plus a long list of surcharges. The concept that decides your bill is dimensional weight: carriers charge for the space a package occupies, not just its mass, because a trailer fills up before it hits its weight limit. The formula is length × width × height in inches, divided by a DIM divisor.
The US Postal Service's Domestic Mail Manual sets this out explicitly for retail Priority Mail: for parcels going to zones 1–9 and exceeding one cubic foot (1,728 cubic inches), you divide the cubic dimensions by 139 and round up to get dimensional weight in pounds, and postage is based on actual weight or dimensional weight, whichever is greater.
UPS and FedEx apply the same idea to their published US domestic rates, and 139 has been the standard published divisor in recent years. Negotiated contracts often specify a different divisor and a different threshold, so read your own contract rather than assuming. Apparel is light and bulky, so apparel parcels are very often billed on dimensional weight, which means your box size is your freight cost.
LTL is priced on weight, distance, and freight class. The National Motor Freight Traffic Association's National Motor Freight Classification assigns every commodity a class from 50 to 500 based on four characteristics:
- density (how heavy the freight is relative to the space it takes up)
- handling (how easy it is to move across a dock)
- stowability (how well it packs into a trailer)
- and liability (how likely it is to be damaged or to damage other freight).
In general, the denser the freight and the easier it is to handle, the lower the class and the lower the rate. Apparel in cartons is light for its volume, so it lands in the middle-to-upper part of the range rather than at the cheap end, but your class comes from the NMFC listing for your specific commodity, not from a rule of thumb, so look it up.
On top of the base rate come accessorials: charges for anything beyond simple dock-to-dock delivery, such as a liftgate, residential delivery, inside delivery, appointment scheduling, limited access, redirecting the shipment, or a second delivery attempt. Accessorials can add a double-digit percentage to an LTL invoice and are the leading source of freight bill disputes.
FTL is priced per mile with a fuel surcharge, plus detention — an hourly charge for holding the driver beyond a free waiting period, commonly two hours. You buy the whole trailer regardless of how full it is, so FTL overtakes LTL on price once a shipment gets large. The crossover point is quoted anywhere from about six to fourteen pallets and does vary by lane, freight class and urgency, so price both ways for your own lanes.
Ocean is priced per container — a 20-foot box (one TEU, or twenty-foot equivalent unit) or a 40-foot box (an FEU) — on a port-to-port basis, plus origin charges, destination charges, and a stack of surcharges. Rates are wildly volatile.
The Freightos Baltic Index, a published daily index of spot container prices, is the most-quoted public benchmark, and it is liquid enough to be traded as a futures contract. Over the past few years its global composite has swung between roughly a thousand and well over ten thousand dollars per 40-foot container. Anyone who quotes you "ocean freight is $X" without a date is guessing, and any spreadsheet that hardcodes an ocean rate is wrong within a quarter.
Air is priced per kilo on chargeable weight (again the greater of actual and volumetric weight) and costs several times ocean per unit.
Who pays what: Incoterms
Incoterms are eleven three-letter codes published by the International Chamber of Commerce that define, in a sales contract, who arranges and pays for transport, who bears the risk, and where risk transfers. The current set is Incoterms 2020. Seven apply to any mode of transport — EXW, FCA, CPT, CIP, DAP, DPU, DDP, and four are for sea and inland waterway only: FAS, FOB, CFR, CIF.
| Term | Plain English | Who arranges main carriage | Who clears import & pays duty |
|---|---|---|---|
| EXW | Ex Works — collect it from my factory door | Buyer (everything) | Buyer |
| FCA | Free Carrier — I hand it to your carrier, cleared for export | Buyer | Buyer |
| FOB | Free On Board — I load it on your vessel (sea only) | Buyer | Buyer |
| CIF | Cost, Insurance and Freight — I pay ocean freight and insurance to your port (sea only) | Seller | Buyer |
| DAP | Delivered At Place — I deliver to your address, you clear customs | Seller | Buyer |
| DDP | Delivered Duty Paid — I deliver everything, duty included | Seller | Seller |
For a US apparel importer buying from Asia, FOB origin port is by far the most common: the factory gets the goods onto the vessel and cleared for export, and from that point you own both the goods and the problem. FOB is popular precisely because it gives you control of the ocean leg, which is the volatile bit.
Note the trap in DDP: it looks convenient, but it makes your supplier the importer of record — the party legally answerable to CBP for the declaration. That means the tariff classification and the duty payment are being decided by someone with no incentive to get it right and no US liability if they do not.
A worked freight-cost example
ONE STYLE, THREE FREIGHT DECISIONS (illustrative rates)
Ridge Jacket. 2,400 units. Carton = 24 units, 22 lb,
24 x 16 x 14 in. 100 cartons total.
A) OCEAN IMPORT, factory (Vietnam) -> Los Angeles
100 cartons = 100 x (24x16x14) = 537,600 cu in = 311 cu ft
40' container usable ~2,350 cu ft -> this is 13% of a box,
so we ship LCL (less than container load) or consolidate.
Ocean freight, share of a 40' container
ASSUMED $3,650/FEU x 13% $475
Origin charges (terminal handling, docs, seal) $310
Destination handling + chassis + drayage LA->DC $690
Customs brokerage entry fee $125
Importer Security Filing fee $35
Duty: ASSUMED 16.0% for this HTS line. LOOK UP
YOUR OWN LINE - apparel rates vary widely
and extra tariff layers change yearly.
2,400 x $18.40 FOB = $44,160 x 16.0% $7,066
Merchandise Processing Fee 0.3464%
$44,160 x 0.003464 = $152.97
(FY2026 min $33.58 / max $651.50 -> in range) $153
Harbor Maintenance Fee 0.125% (ocean only) $55
-------
LANDED FREIGHT + DUTY $8,909
Per unit $3.71
FOB cost $18.40 -> LANDED COST $22.11/unit
B) OUTBOUND WHOLESALE, 20 cartons to a retailer DC (LTL)
20 cartons x 22 lb = 440 lb on 1 pallet
Density: 20 x 3.11 cu ft = 62.2 cu ft (+ pallet ~5)
440 lb / 67 cu ft = 6.6 lb/cu ft -> a middling class
Base LTL rate, 440 lb, 700 mi (assumed) $268
Fuel surcharge 28% $75
Accessorials: appointment $45 + liftgate $95 $140
-------
TOTAL LTL $483
Per unit (480 units) $1.01
Same shipment, class declared too low: $196
-> carrier re-weighs, reclasses, rebills.
You get a correction invoice 6 weeks later.
C) OUTBOUND DTC, one jacket in a 14x11x4 poly mailer
Actual weight 1.9 lb
Dimensional: 14 x 11 x 4 = 616 cu in
616 < 1,728 cu in -> DIM does not apply (USPS rule)
Billable weight = 1.9 lb -> round to 2 lb
Same jacket in a 16x12x10 BOX because packing grabbed
the wrong carton:
16 x 12 x 10 = 1,920 cu in > 1,728
1,920 / 139 = 13.8 -> 14 lb billable
Actual 2.2 lb, billed as 14 lb.
Zone 6 ground (assumed): ~$11.90 vs ~$25.40
-> +$13.50 per order
At 95,000 orders/yr, choosing the wrong box on just
10% of them costs $128,250/year.
Take each block in turn. Block A shows why your margin calculations must use landed cost — the total cost to get one unit into your warehouse, including freight, duty and fees — rather than the FOB price you paid the factory. Freight and duty added $3.71 to a garment that cost $18.40, a 20% increase, and the duty alone is almost four times everything else in the block put together.
It also shows the three US import charges stacking: duty, the Merchandise Processing Fee at 0.3464% of value (bounded in fiscal year 2026 at a minimum of $33.58 and a maximum of $651.50 per entry under CBP Decision 25-10), and the Harbor Maintenance Fee at 0.125%, which applies to ocean but not to air.
The 16% duty rate in the example is an assumption for illustration only. Apparel duty rates differ by fiber, construction and gender, and the additional tariff layers of the last two years have moved repeatedly — see the next section.
Block B shows freight class in action. Apparel in cartons is not dense, so it classes higher and costs more per pound than dense freight would. It also shows the accessorial problem — appointment scheduling and a liftgate added $140, which is 29% of the $483 invoice and 41% on top of the base rate plus fuel, and what happens when you declare the class optimistically: carriers re-weigh and re-class freight routinely, and the correction arrives weeks after you paid.
Block C surprises people most. The same garment in the wrong-sized box costs more than double to ship, purely on dimensional weight, and a packing bench that grabs a box one size too big on one order in ten costs six figures a year at moderate volume.
That is why box-size selection belongs in software. The name for it is cartonization: the system works out which box each order fits into and tells the packer, instead of leaving it to a tired human's judgment at 4:55pm.
Carton dimensions, units per carton, box sizes at the packing bench, and which DC ships which ZIP code are all software decisions with five- and six-figure annual consequences. Store dimensions and weights on the SKU and on the carton, not in someone's head. If your pack station cannot tell an operator which box to use, you are paying for air by the pound.
Customs and import mechanics at the operational level
The broker, the entry and the bond
When goods arrive in the US, someone must file an entry with CBP: a declaration of what the goods are, their tariff classification under the Harmonized Tariff Schedule, their value, their country of origin, and the duty owed. Almost nobody files their own. You appoint a licensed customs broker and give them a power of attorney, which is a signed document authorizing them to act for you.
You also need a customs bond. A bond is a three-party guarantee between you (the principal), a surety company (an insurer that stands behind you), and CBP, promising that duties and penalties will be paid. You can buy a single transaction bond covering one shipment, or a continuous bond covering a year of imports; anyone importing regularly buys continuous.
CBP's regulations do not fix a flat amount. Under 19 CFR 113.13, bond amounts are set by considering your payment record, your compliance record, the value and nature of the goods, and the level of CBP supervision required, and CBP reviews bond sufficiency periodically and can require you to obtain a larger bond. In practice continuous bonds are sized in proportion to the duties, taxes and fees you paid over the previous twelve months, subject to a floor that your broker will quote you.
One consequence trips importers up regularly: if your duty bill jumps, which it does when tariff policy changes, your existing bond becomes insufficient and your entries can stop until you top it up. Watch this, and put the trigger in your software.
Duty rates are data that change
This is the most volatile subject in the chapter, so treat every number below as a snapshot with a date on it.
Two things are stable. First, apparel has historically been one of the highest-duty categories in the US tariff schedule, well above the average for manufactured goods. Second, the rate is set line by line: two jackets that look identical can carry very different rates depending on fiber content, knit versus woven construction, and how the garment is described. There is no single "apparel duty rate," and any ERP that stores one is storing a bug.
Everything else has moved repeatedly. The sequence, with dates, because the dates are the lesson:
- April 2025. A broad set of country-specific "reciprocal" tariffs was imposed under the International Emergency Economic Powers Act (IEEPA), on top of normal tariff-schedule rates. Vietnam, a major apparel sourcing country, was announced at 46% on 2 April 2025 and then cut to 20% that July. Rates moved that far, that fast, for a lot of countries.
- 29 August 2025. The de minimis exemption ended globally under Executive Order 14324. De minimis was the rule that let shipments valued under $800 enter the US duty-free and with minimal paperwork. It was the entire economic basis of direct-from-Asia parcel selling, and its removal means small parcels now need formal treatment and pay duty. For an apparel brand this cuts both ways: your overseas competitors lost their price advantage, and any direct-ship or drop-ship flow you run from an overseas factory now carries duty and a customs filing per parcel. The closure survived the court ruling described below and was still in force as of July 2026.
- 20 February 2026. The Supreme Court ruled 6–3 in Learning Resources, Inc. v. Trump that IEEPA does not authorize the President to impose tariffs, striking down the reciprocal tariff regime. Roughly $166 billion collected from more than 330,000 businesses became refundable. CBP opened its CAPE refund-claims portal in April 2026, and about $81 billion had been paid back by July 2026.
- After the ruling. A 10% global tariff was imposed instead under Section 122 of the Trade Act of 1974, a balance-of-payments power with a hard 150-day time limit that ran out on 24 July 2026. The Court of International Trade, the specialist federal court that hears customs and trade cases, ruled those replacement tariffs illegal too, and that decision went to appeal. As of July 2026 the legal basis for a broad US tariff was still moving. Whatever rate you read anywhere, including in this book, confirm it with your broker before you price a season.
- Throughout. Section 232 tariffs — a separate national-security power that targets named product categories rather than named countries — stayed in force on steel and aluminum, copper, vehicles and others. They do not target apparel directly, but they raise the cost of packaging, racking, fixtures and equipment.
Draw one engineering conclusion from that sequence of dates: a duty rate is a fact about one customs entry on one date, and it belongs to that entry. Store the rate that was actually applied on each customs entry line, store the entry date, allocate the resulting duty to the units received, and never compute historical margin using today's rate. Your landed-cost report must be able to say "this batch cost 16%, that batch cost 36%," because in 2025 and 2026 that was literally true for identical goods.
ISF and its unforgiving clock
For ocean shipments, the Importer Security Filing — universally called "ISF" or "10+2" — is a separate, earlier filing from the entry. It is governed by 19 CFR Part 149. Ten data elements come from you, the importer, and two from the carrier.
ISF 10+2, AND WHEN EACH PIECE IS DUE (19 CFR 149.2-149.3)
DUE 24 HOURS BEFORE THE CARGO IS LOADED ON THE VESSEL
AT THE FOREIGN PORT:
1 Seller (name/address, or accepted ID)
2 Buyer
3 Importer of record number (IRS/EIN/SSN/CBP number)
4 Consignee number(s)
5 Manufacturer (or supplier)
6 Ship-to party
7 Country of origin
8 Commodity HTSUS number (6-digit minimum)
Elements 5, 7 and 8 must be LINKED to each other at
line-item level (19 CFR 149.3(a)).
Elements 5-8 may be filed on best available data and
updated, but no later than 24 h before US arrival.
DUE AS EARLY AS POSSIBLE, AND NO LATER THAN 24 HOURS
BEFORE ARRIVAL AT THE US PORT:
9 Container stuffing location
10 Consolidator (whoever packed the container)
FILED BY THE CARRIER (the "+2"):
vessel stow plan
container status messages
BOND REQUIRED: the ISF importer must hold a basic import,
custodial, carrier, FTZ operator, or ISF bond (19 CFR 149.5).
PENALTY: the ISF bond in 19 CFR part 113, appendix D
provides for LIQUIDATED DAMAGES OF $5,000 FOR EACH
VIOLATION on default.
Timing is what that block is really about. Eight of the ten elements are due 24 hours before the box is loaded onto a ship on the other side of the world. The clock runs off the loading date at the foreign port, which is weeks before the goods reach you.
That means your ERP must know the buyer, seller, manufacturer, ship-to party, country of origin and six-digit HTS code for every line on a PO roughly four weeks before the goods reach you. If your product data is incomplete at that point, your broker files placeholders, and placeholders are how you end up on CBP's radar.
"Liquidated damages" means a penalty amount agreed in advance in the bond, so nobody has to argue about the size of the loss: the $5,000-per-violation figure is written directly into the ISF bond text in appendix D to 19 CFR part 113, and CBP can assess it for late filings, inaccurate filings, and filings never made.
Examinations, holds and the demurrage clock
CBP can select any container for examination. The mild version is an X-ray or gamma-ray scan of the whole container, which adds a day or two.
The severe version is a full intensive exam, where the container is moved to a Centralized Examination Station (a private, CBP-approved facility that opens and inspects containers) and unloaded by hand; that can take one to three weeks, and the exam and handling fees run into four figures per container — the amount varies by port, station and container size, and you pay it whether or not anything is found.
While your container waits, two clocks run. Demurrage is charged by the terminal for the container sitting in their yard past the free time allowed. Detention (also called per-diem) is charged by the ocean carrier for you keeping their container past free time once you have collected it. Both accrue daily, both escalate in tiers, and both run to hundreds of dollars per container per day.
There is real regulatory protection here that most importers do not use. The Federal Maritime Commission's demurrage and detention billing rule, 46 CFR part 541, requires that a demurrage or detention invoice be issued within 30 calendar days of the date the charge was last incurred, and states plainly that if it is not, the billed party is not required to pay the charge.
The rule also lists mandatory invoice contents at 46 CFR 541.6:
- the bill of lading and container numbers
- the port of discharge
- why you are the right party to bill
- the invoice and due dates
- the free-time start and end dates
- the specific days charged
- the total due
- the tariff rule or contract clause the daily rate comes from
- the rate itself
- and contact details plus a digital channel such as a URL or QR code for questions or for a request to reduce, refund or waive the fee.
Section 541.5 then says outright that "failure to include any of the required minimum information in this part in a demurrage or detention invoice eliminates any obligation of the billed party to pay the applicable charge." Section 541.8 gives you at least 30 calendar days from the invoice date to request mitigation, refund or waiver.
Demurrage and detention invoices routinely arrive late, or without the required rate basis, free-time dates or dispute contact. Under the FMC rule those are unenforceable. Your ERP should date-stamp when each charge was last incurred and when the invoice arrived, and flag any invoice outside the 30-day window automatically. For an importing brand this is one of the highest-return pieces of software you can write, because it turns a regulation you already benefit from into money you actually keep.
Foreign trade zones and bonded warehouses
A foreign trade zone (FTZ) is a secured area, legally treated as outside US customs territory for duty purposes, though physically inside the country. Zones are authorized by the Foreign-Trade Zones Board under the Foreign-Trade Zones Act, and CBP's operational rules live in 19 CFR part 146.
The mechanics: goods are admitted to a zone on CBP Form 214, and each admission gets a unique sequential number that everything downstream traces back to. At admission you elect a zone status:
- nonprivileged foreign (duty determined when it leaves, based on its condition then)
- privileged foreign (duty rate locked at admission)
- zone restricted
- or domestic.
Duty is paid when goods are transferred into US customs territory for consumption, not on admission, and goods re-exported directly from the zone never pay US duty at all.
For a wholesale apparel brand that means three benefits:
- Duty deferral: you pay when you ship to a customer, not when the container lands — real cash flow for a business that imports a season three months before it sells.
- No duty on re-exports, which matters if you supply Canadian or European accounts from a US DC.
- And weekly entry, where 19 CFR 146.63(c) lets the port director accept a single estimated entry covering a whole calendar week's removals instead of one entry per shipment, collapsing many Merchandise Processing Fee charges into one.
Conditions apply, so confirm your eligibility with your broker.
The costs are real. The zone operator is liable under bond for the merchandise as described on the Form 214, and part 146 imposes strict inventory control:
- every unit must trace back to a Form 214;
- an admission discrepancy goes to CBP on Form 5931 within 20 days of admission (19 CFR 146.37), and an overage found later needs an admission application within 5 days (19 CFR 146.53);
- and the operator must maintain an audit trail from admission, through any handling, to transfer.
Meeting that is a software job before it is a paperwork job, and it is the main reason small brands do not run their own zone.
A bonded warehouse is the lighter-weight cousin: a CBP-licensed facility where imported goods can sit duty-unpaid for up to five years, with duty payable on withdrawal. Less flexible than an FTZ but much easier to set up, because you use someone else's license. The practical sequence for most brands is: start with normal entry, move to a bonded 3PL if duty timing hurts your cash flow, and pursue FTZ status only when your duty bill is large enough that the compliance overhead pays for itself.
Returns operations
Returns are the outbound process run backwards, badly, one item at a time, with no advance notice. That sentence is the whole section; the rest of it fills in the detail and the cost.
How much comes back
The scale is large. The National Retail Federation and Happy Returns reported that retailers expected 15.8% of annual sales to be returned in 2025, totaling $849.9 billion, down from 16.9% and $890 billion in 2024. Online is worse: an estimated 19.3% of online sales were expected to come back in 2025, and 17% of holiday sales.
Apparel sits at or above the online average because of fit — a garment is the one category where you cannot tell if it works until it is in your house. Rates in the 20–30% range are commonly reported for DTC apparel, and higher for tailored or hard-to-fit categories, but this varies widely by brand, price point and how generous your policy is. Measure your own.
The reverse flow, step by step:
REVERSE FLOW: ONE RETURNED JACKET
1 RMA created customer requests return online
(or ships back with no RMA at all)
2 Transit in one parcel, arriving unannounced
3 Receive open, identify SKU, match to RMA
and to the original order
4 Inspect and GRADE
A new, tags on, resaleable -> restock
B like-new, needs steam/refold/re-tag -> refurb
C worn/marked, not resaleable at full -> outlet
D damaged/soiled -> liquidate
E wrong item / not ours / empty box -> fraud queue
5 DISPOSITION move to the right location & pool
6 REFUND / EXCHANGE trigger financial event
7 LEDGER post the inventory movement with
a disposition reason code
COST PER RETURN, DTC apparel (illustrative build-up;
only the $4.06 processing fee is a survey average)
inbound return shipping (if you pay) $7.50
3PL returns processing fee (survey) $4.06
refurbishment (steam, refold, re-poly, re-tag) $1.80
payment processing not refunded $0.90
average value lost to markdown on grade C/D $6.20
------
~ $20.46 per return, against a $95 order
Outbound pick&pack for the same order (survey): $3.20
RETURNS COST ROUGHLY 6x THE ORIGINAL PICK COST
Why a return costs several times the original shipment
The reasons are structural. Forward, you know what is coming, it is already in a known location, and it moves in a batch with a hundred other orders. Backward, every parcel is a surprise, contains an unknown item in an unknown condition, and must be handled individually by someone qualified to make a judgment call.
Step 4, grading, is the expensive step: it cannot be batched and it cannot be done by an untrained temp. Step 3 is expensive when the customer did not use an RMA, because now someone has to work out whose order this was.
The dollar amounts above are illustrative except the two marked as survey averages, but the ratio is the durable lesson: processing a return costs several times what shipping the order cost in the first place.
Grading speed and markdown risk
Speed matters enormously in apparel because of markdown risk. A jacket returned in week 3 of a 12-week season goes straight back into full-price inventory. The same jacket returned in week 3 but sitting in a returns backlog until week 9 gets marked down. So set an explicit throughput target for the returns bench, returns processed per labor hour, and publish it the way you publish picking rates.
Two practices are worth adopting whatever your volume: photograph every returned item on receipt and again after any rework, so condition disputes have evidence, and weigh the inbound parcel and compare it against the expected weight of what should be inside.
Return fraud is now material
Fraud deserves a mention because it is now material and it is an ERP problem. The 2025 NRF and Happy Returns report found that 9% of all returns are fraudulent. The patterns retailers most often report are returns claiming more units than were actually sent back, empty-box returns, and returns of counterfeit items swapped for the genuine article.
The software defenses are unglamorous and effective:
- weigh inbound returns and compare against expected weight
- photograph on receipt
- track return rate per customer
- and require an RMA that is scannable.
Give returns their own dock, staff and metrics
At a fifth to a third of DTC volume, returns are your second-largest inbound flow after container receipts. Give them their own dock area, their own staff, their own metrics and their own locations in the ERP. Brands that treat returns as an interruption to "real" work end up with a pile of unprocessed parcels that is simultaneously a customer service crisis and a chunk of missing inventory.
Peak season and labor
A wholesale apparel brand has a lumpy year, and the lumps come from two different calendars that do not line up.
The wholesale calendar peaks at delivery windows. Spring goods ship January–March, fall goods ship July–September, and within each window there is a brutal concentration in the last ten days before the retailer's cancel date. The DTC calendar peaks at Black Friday through mid-December, plus whatever promotional moments you create. So a brand doing both faces a wholesale peak in late summer, a DTC peak in late fall, and a wholesale spring peak in the depths of January — three surges, none of which are the same shape.
Plan from the peak day, not the average day
Capacity planning starts from the peak day, not the average day. Compute it explicitly.
PEAK CAPACITY PLAN, CYBER WEEK (illustrative)
Baseline 380 orders/day
Peak multiplier (Cyber Mon) 5.5x
Peak day volume 2,090 orders
Throughput per person per hour (use YOUR measured rates)
pick (batch, 2.4 lines/order) 62 lines/h
pack (DTC single) 34 orders/h
ship label / sort 95 orders/h
Peak day labour requirement (8 productive hours)
picking 2,090 x 2.4 / 62 / 8 = 10.1 heads
packing 2,090 / 34 / 8 = 7.7 heads
shipping 2,090 / 95 / 8 = 2.8 heads
replen, QC, supervision = 3.0 heads
----------
TOTAL 23.6 -> 24 heads
Core permanent team 9 heads
TEMPORARY LABOUR NEEDED 15 heads
Ramp requirement
hire by Nov 1 (4 weeks before peak)
train 2 days classroom + 3 days buddy
productivity curve wk1 55%, wk2 75%, wk3 90%, wk4 100%
-> hire 18 to have 15 productive on peak day
(attrition in seasonal warehouse work runs high)
The throughput rates in that plan are placeholders. Measure your own from your own task logs, because they differ by building, by product and by whether your pickers are scanning or reading paper. What does not change is the method: start from the peak day, divide by realistic hourly rates, and add the roles nobody budgets for (replenishment, quality checks, supervision).
Ramp, attrition and who else is hiring
The two most-missed lines are the ramp and the attrition. A temp hired the day before peak produces roughly half what a trained person produces, so hiring late costs more and delivers less. And seasonal warehouse attrition runs high, so plan to over-hire — a 15–25% cushion is a common planning assumption — or you will be short on the day that matters.
Understand also who you are competing with. Every fall the large parcel carriers, national retailers and big 3PLs each hire seasonal workers in the tens of thousands, and the largest hire in the hundreds of thousands; the NRF publishes an industry-wide seasonal hiring forecast each October.
Two things follow for a small brand. First, you are bidding for the same people as employers who can pay more and hire faster than you. Second, your staffing agency's supply gets scarce in exactly the weeks you need it. Book early, agree the rate early, and treat the agency relationship as a supplier relationship with an SLA, agreed long before November.
Getting the wage number right
On wage levels, do not use a number from a book — including this one. Warehouse pay varies by metro area more than by anything else, and it has moved fast in recent years. Pull the current figure for warehousing and storage from the Bureau of Labor Statistics for your own market, then apply a fully-loaded multiplier to cover payroll taxes, workers' compensation, benefits and paid time off. A multiplier in the region of 1.25–1.45× base wage is a common planning assumption; your accountant can give you the real one from last year's payroll. Model with the loaded number, always, because that is what an hour actually costs you.
Metrics for the operation
You cannot manage a warehouse on gut feel, because everything happens in seconds and nothing is visible from the office. The core metric set follows, with what each one actually measures and an honest range.
| Metric | Definition | What it tells you | Realistic range |
|---|---|---|---|
| Units per labor hour (UPH) | Units picked (or packed) ÷ productive hours on that task | Labor efficiency; the denominator of cost per order | Wildly profile-dependent and not comparable between buildings. The 2025 industry survey self-reported about 102 picks per hour per person; other years and other definitions produce figures half that. Measure your own and compare only against yourself |
| Order cycle time | Order received → order shipped, elapsed | Customer-facing responsiveness | DTC same-day if before cut-off; wholesale measured against the ship window, not hours |
| Dock-to-stock | Truck arrival → goods available to sell | How fast new receipts become revenue; a leading indicator of available-to-sell accuracy | 24–72 h is a common SLA; under 24 h is strong |
| Pick accuracy | Lines picked correctly ÷ total lines picked | Downstream returns, chargebacks and customer complaints | 2025 industry self-report 99.42%; 99.9% needs scan verification at pack |
| Inventory record accuracy (IRA) | Locations where counted qty = system qty ÷ locations counted | Whether your available-to-sell numbers can be trusted | Target 99%+ at location level. Below about 97% and picking degrades visibly |
| Cost per order | Total fulfillment cost (labor + facility + consumables + VAS, excluding freight) ÷ orders shipped | The single number that lets you compare in-house against a 3PL quote | Build it bottom-up for your operation; benchmark the pick-and-pack component against the $3.20 B2C survey average and add your own extra services |
| On-time in full (OTIF) | Orders delivered complete within the agreed window ÷ total orders | The metric retailers grade you on and fine you against | Retailer thresholds commonly sit in the mid-to-high 90s; below the threshold, chargebacks |
| Shrinkage rate | Unexplained inventory loss at cost ÷ cost of goods sold | Process discipline plus theft | NRF retail average about 1.6% of sales (FY2022); 3PL self-report 2.68% (2025). Different denominators — do not compare them directly |
Measure consistently, and pair the metrics
Metrics come with two warnings. First, measure them consistently or do not measure them. UPH computed on clocked hours means something different from UPH computed on task-logged hours, and the second one always looks better. That is exactly why published industry averages for picks per hour swing so widely between years and surveys: different people are dividing by different denominators. Pick one definition, write it down, and never change it silently.
Second, every metric creates a behavior. Measure pickers on UPH alone and pick accuracy falls; measure on accuracy alone and throughput falls. Pair them: publish UPH and accuracy together, per person, weekly.
What this means for your ERP
Everything above translates into schema, workflows, rules and reports. The concrete translation follows.
Tables and fields this chapter demands
-- Physical geography. Every quantity lives at a location.
create table warehouses (
id uuid primary key,
tenant_id uuid not null,
code text not null, -- 'LAX1'
is_3pl boolean not null default false,
provider_name text,
timezone text not null,
unique (tenant_id, code)
);
create type location_kind as enum
('pick_face','reserve','goh','staging','dock','returns',
'qc_hold','damage','ftz','transit');
create table locations (
id uuid primary key,
tenant_id uuid not null,
warehouse_id uuid not null references warehouses(id),
code text not null, -- 'A-12-03-B' fixed width
zone text not null, -- 'A'
aisle smallint,
bay smallint,
level text,
kind location_kind not null,
uom text not null default 'each', -- each|inner|carton
pick_sequence integer not null, -- serpentine route order
is_pickable boolean not null default true,
is_sellable boolean not null default true, -- qc_hold => false
max_units integer,
replen_min integer,
replen_max integer,
unique (tenant_id, warehouse_id, code)
);
create index on locations (tenant_id, warehouse_id, pick_sequence);
-- Inbound: appointment -> ASN -> receipt -> discrepancy
create table inbound_appointments (
id uuid primary key,
tenant_id uuid not null,
warehouse_id uuid not null references warehouses(id),
scheduled_at timestamptz not null,
dock_door text,
carrier_scac text, -- carrier's 4-letter code
container_no text,
status text not null -- booked|arrived|closed
);
create table asns (
id uuid primary key,
tenant_id uuid not null,
purchase_order_id uuid not null,
supplier_id uuid not null,
asn_number text not null,
ship_date date,
eta date,
appointment_id uuid references inbound_appointments(id),
unique (tenant_id, supplier_id, asn_number)
);
create table asn_cartons (
id uuid primary key,
tenant_id uuid not null,
asn_id uuid not null references asns(id),
sscc text not null, -- GS1 SSCC-18, AI (00)
gross_weight_lb numeric(10,3),
length_in numeric(8,2), width_in numeric(8,2),
height_in numeric(8,2),
unique (tenant_id, sscc) -- SSCC is globally unique
);
create table asn_carton_lines (
id uuid primary key,
tenant_id uuid not null,
carton_id uuid not null references asn_cartons(id),
sku_id uuid not null,
quantity integer not null check (quantity > 0)
);
create type discrepancy_kind as enum
('short','over','damaged','wrong_sku','no_asn','carton_missing');
create table receipt_discrepancies (
id uuid primary key,
tenant_id uuid not null,
receipt_id uuid not null,
purchase_order_line_id uuid,
sku_id uuid not null,
kind discrepancy_kind not null,
expected_qty integer not null,
received_qty integer not null,
photo_urls text[],
resolved_at timestamptz,
resolution text
);
-- Counting. A count posts evidence. It never edits a quantity.
create table cycle_count_tasks (
id uuid primary key,
tenant_id uuid not null,
location_id uuid not null references locations(id),
sku_id uuid,
abc_class char(1), -- A|B|C
trigger text not null, -- scheduled|negative|
-- short_pick|complaint
assigned_to uuid,
counted_qty integer,
system_qty_at_count integer,
variance integer generated always as
(counted_qty - system_qty_at_count) stored,
variance_value_cents bigint,
status text not null, -- open|counted|
-- investigating|resolved
root_cause text, -- mislocation|theft|
-- receipt_error|damage|
-- uom_error|unexplained
resolved_at timestamptz
);
-- Outbound work
create table pick_waves (
id uuid primary key,
tenant_id uuid not null,
warehouse_id uuid not null references warehouses(id),
method text not null, -- discrete|batch|zone|
-- wave|pick_and_pass
channel text not null, -- wholesale|dtc
cutoff_at timestamptz,
released_at timestamptz,
completed_at timestamptz
);
create table pick_tasks (
id uuid primary key,
tenant_id uuid not null,
wave_id uuid references pick_waves(id),
order_line_id uuid not null,
location_id uuid not null references locations(id),
sku_id uuid not null,
qty_requested integer not null,
qty_picked integer,
tote_id text,
picker_id uuid,
started_at timestamptz,
completed_at timestamptz,
short_reason text
);
-- Outbound cartons carry an SSCC too, and feed the EDI 856
create table outbound_cartons (
id uuid primary key,
tenant_id uuid not null,
shipment_id uuid not null,
sscc text not null,
carton_seq integer not null,
weight_lb numeric(10,3) not null,
length_in numeric(8,2), width_in numeric(8,2),
height_in numeric(8,2),
dim_divisor integer not null default 139, -- per YOUR contract
dim_weight_lb numeric(10,3) generated always as
(ceil((length_in*width_in*height_in)/dim_divisor)) stored,
tracking_number text,
unique (tenant_id, sscc)
);
-- Value-added services are jobs with a measurable cost
create table vas_jobs (
id uuid primary key,
tenant_id uuid not null,
job_type text not null, -- ticket|reticket|polybag|
-- goh|steam|kit|inspect|security
order_id uuid,
customer_id uuid, -- which retailer required it
sku_id uuid,
units integer not null,
rate_cents integer, -- per unit or per hour
rate_basis text not null, -- per_unit|per_hour
labour_minutes integer,
cost_cents bigint,
started_at timestamptz,
completed_at timestamptz
);
-- Import: one row per customs entry, allocated to receipts.
-- Duty rate is stored PER LINE because it changes over time.
create table customs_entries (
id uuid primary key,
tenant_id uuid not null,
entry_number text not null,
broker_id uuid,
container_no text,
isf_filed_at timestamptz,
isf_lading_at timestamptz, -- the 24h clock reference
entry_date date,
duty_cents bigint,
mpf_cents bigint,
hmf_cents bigint,
broker_fee_cents bigint,
freight_cents bigint,
exam_type text, -- none|scan|intensive
exam_fee_cents bigint,
ftz_admission_no text, -- CBP Form 214 number
zone_status text, -- npf|pf|zone_restricted|domestic
unique (tenant_id, entry_number),
constraint isf_on_time
check (isf_filed_at is null or isf_lading_at is null
or isf_filed_at <= isf_lading_at - interval '24 hours')
);
create table customs_entry_lines (
id uuid primary key,
tenant_id uuid not null,
entry_id uuid not null references customs_entries(id),
sku_id uuid not null,
hts_code text not null, -- 10 digits as filed
country_of_origin char(2) not null,
units integer not null,
customs_value_cents bigint not null,
-- the rate ACTUALLY APPLIED on this date:
base_duty_rate_bp integer not null, -- basis points
extra_tariff_rate_bp integer not null default 0,
duty_cents bigint not null
);
-- Demurrage / detention: enforce the FMC 30-day rule in software
create table accessorial_invoices (
id uuid primary key,
tenant_id uuid not null,
container_no text not null,
charge_type text not null, -- demurrage|detention|other
charge_last_incurred_on date not null,
invoice_issued_on date not null,
amount_cents bigint not null,
has_rate_basis boolean not null default false,
has_free_time_dates boolean not null default false,
has_dispute_contact boolean not null default false,
disputable boolean generated always as (
invoice_issued_on > charge_last_incurred_on + 30
or not has_rate_basis
or not has_free_time_dates
or not has_dispute_contact
) stored,
disputed_at timestamptz,
outcome text
);
What follows is a guided tour of the choices in that schema, table by table.
warehouses carries an is_3pl flag, because a partner site and your own site behave differently in almost every report that follows. locations carries pick_sequence as a separate integer from the human-readable code, so you can implement serpentine routing even if your codes do not sort into a sensible walking order on their own. Its is_sellable column is what your available-to-sell query joins on, so QC-hold stock is excluded from availability in one place rather than in twenty separate queries.
The inbound chain runs inbound_appointments → asns → asn_cartons → asn_carton_lines. That is the three-way match modeled directly: the appointment says a truck is coming, the ASN says what is on it, and the carton rows say which SKUs are in which box. Anything that fails the match lands in receipt_discrepancies, with photographs attached, so the evidence outlives the argument with the supplier.
asn_cartons.sscc has a unique constraint because an SSCC is meant to be unique worldwide. If a supplier reuses one, you want a loud database error rather than a quiet mystery six weeks later.
cycle_count_tasks stores system_qty_at_count as a snapshot, because by the time anyone investigates, the live quantity has already moved. Its root_cause column uses a closed list of values so your shrink report can group by it.
pick_waves and pick_tasks are separate tables because a wave is a planning object with a cut-off time, while a task is a unit of work with a picker and a stopwatch. Keeping them apart is what lets you measure units per labor hour later. vas_jobs gives every piece of compliance work a customer, a unit count, a rate and a duration, which is how you eventually answer what one retailer's ticketing rules actually cost you.
outbound_cartons stores the DIM divisor next to the computed dimensional weight, because 139 is only the published default and your contract may say otherwise. Freight cost then becomes computable at the packing bench instead of being discovered on an invoice.
customs_entry_lines exists because a duty rate is an event: storing the base rate and any extra tariff layer per line, per entry, is the only way your landed-cost history survives a year like 2025. Those rates are held in basis points, where one basis point is one hundredth of one percent, so 16% is 1,600 basis points. Whole numbers are used because they do not drift the way stored decimals sometimes do.
Finally, accessorial_invoices.disputable encodes the FMC rule as a generated column — a column the database computes for you from other columns in the same row, so it can never fall out of step. Any invoice that arrives more than 30 days after the charge was last incurred, or that is missing required content, lights itself up without anyone remembering to check.
Workflows and screens the software must support
- Dock schedule board. Appointments by door and hour, searchable by container number, PO number and carrier. Must load on a phone in a yard with two bars of signal.
- Scan-to-receive. Scan the carton's SSCC → system shows expected contents → confirm or flag. Blind-count mode for unlabeled freight. Photo capture on any discrepancy.
- Directed put-away. System proposes a location based on velocity class, zone, unit-of-measure and available capacity; operator scans the location to confirm. Scanning a different location must be allowed but must record an override.
- Replenishment queue. Generated from min/max plus the demand in the released wave, prioritized by which pick face will empty first.
- Wave planner. Select orders by channel, carrier, ship date and cut-off; preview line count, unit count and estimated labor hours before releasing.
- Mobile pick screen. One line at a time, big type, location code prominent, scan-to-confirm both location and SKU, and a short-pick button that automatically raises a cycle count task.
- Pack station. Cartonization suggestion (which box size to use), scan-verify every unit into the carton, print the carton label with its SSCC, capture weight from a connected scale.
- Blind cycle count. Never display expected quantity. Second-count workflow for variances above the value threshold. Investigation notes required before resolution.
- Returns bench. Scan the parcel → find the order → grade (A–E) → photograph → disposition → refund. Weight comparison against expected as a fraud check.
- VAS work order. Instruction sheet, unit count, start/stop timing, cost capture, linked to the order line that required it.
- Landed cost allocation screen. Attach a customs entry and its freight invoices to a receipt, allocate by value or by unit, and show the resulting per-unit landed cost before posting.
- 3PL invoice reconciliation. Import the 3PL's billing file, match every line against your own record of receipts, orders, storage days and VAS jobs, and surface unmatched lines. Use the spreadsheet import machinery from chapter 7.
Rules that must be enforced
- Quantity on hand is never writable. It is the sum of append-only ledger entries (chapter 1). No screen, no endpoint, no admin tool may set it directly.
- Every ledger entry carries a location and a reason code from a closed list. A movement without a location is not a movement.
- QC-hold and damage locations are excluded from available-to-sell by the
is_sellableflag, and the exclusion is enforced in one place, not repeated in every query. - Cycle count variance above a value threshold cannot post until it has a second count and a root cause. Below the threshold it posts with reason
SHRINK_UNEXPLAINED. - A pick task may only be confirmed by scanning both the location and the SKU. Manual override is allowed but recorded with the operator's identity.
- SSCC values are unique and never reused, inbound or outbound.
- Ship confirm is a single idempotent transaction (chapter 3) that posts the ledger entry, stamps the shipment, queues the EDI 856 and releases invoicing. A retry must not double-ship or double-invoice.
- ISF must be filed at least 24 hours before lading. Enforce it as a check constraint, and alert on any PO whose product data is still incomplete 35 days before the estimated arrival.
- Duty rates are stored per entry line, never hardcoded. The rate that applied in March may not be the rate that applies in September, and your margin history has to reflect that.
- Landed cost is allocated to receipt lines, not expensed centrally. Freight, duty, MPF, HMF, brokerage and exam fees allocate by value or by unit onto the units received, so margin reporting is honest.
- Demurrage and detention invoices are date-checked automatically against the 30-day FMC window and flagged as disputable.
Reports people will demand within the first month
- Open ASNs and expected receipts by week, with units and cube, so the warehouse can staff.
- Dock-to-stock aging — every receipt not yet available to sell, with hours elapsed. This is the report that explains why sales cannot sell a container that landed on Tuesday.
- Inventory record accuracy by ABC class and by zone, monthly, with the trend.
- Shrink by root cause, valued at cost. If "unexplained" is not the smallest category, your investigation process is not working.
- Pick accuracy and UPH by picker, weekly, published together.
- Cost per order by channel, with the components broken out, alongside the equivalent 3PL rate-card cost.
- OTIF by retailer, with the misses categorized into late, short and non-compliant.
- Chargebacks by retailer and reason code, netted against the invoice they were deducted from. Wholesale brands are routinely astonished by this number the first time they see it.
- Landed cost per SKU and per receipt, showing FOB, freight, duty and fees separately, with the duty rate that was actually applied.
- Returns funnel: received, graded, dispositioned, restocked, with aging on each stage and value at risk from markdown.
- Storage cost per SKU per month, ranked descending. This is how you find the carryover style quietly eating pallet positions all year.
Connections to the engineering chapters
- Chapter 1 (append-only ledger) is the backbone of this entire chapter: receipts, put-aways, replenishments, picks, ship confirms, count adjustments, returns and disposition changes are all ledger entries, and the variance discipline above is only possible because nothing is ever overwritten.
- Chapter 2 (Postgres) supplies the enums, generated columns, check constraints and partial indexes shown in the schema above.
- Chapter 3 (concurrency and idempotency) governs scan events, which arrive out of order, in duplicate, and from devices whose network dropped mid-transaction — every scan endpoint needs an idempotency key.
- Chapter 4 (integrations) covers the EDI documents that carry all of this: 856 (advance ship notice), 810 (invoice), 940 (warehouse shipping order to a 3PL), 945 (warehouse shipping advice back), 943/944 (stock transfer advice), 947 (warehouse inventory adjustment advice) and 846 (inventory advice).
- Chapter 5 (multi-tenancy and row-level security) matters if you operate more than one brand or share a 3PL's data feed.
- Chapter 6 (offline sync) is not optional here — warehouse Wi-Fi has dead zones, and a scanner must keep working through them and reconcile afterwards.
- Chapter 7 (spreadsheet imports) is how 3PL invoices, carrier billing files and physical count sheets actually arrive.
- Chapter 8 (available-to-sell caching and reporting) is directly downstream of location-level
is_sellableand dock-to-stock time. - Chapter 9 (testing and ops) should include a seeded warehouse fixture, because a picking bug that ships the wrong size usually reaches a customer before anyone else notices.
- Chapter 11 (reference schema) is where the tables above land in canonical form, and chapter 12 should sequence them: locations and the ledger first, scan-to-receive and directed put-away second, waves and pick tasks third, VAS and landed cost fourth, and the 3PL reconciliation and demurrage audit tooling once the volume justifies them.
Build for the person holding a scanner in a cold building at 7am. The analyst with a laptop can wait. If a screen needs more than one tap per physical action, it will be worked around, and the workaround will be a paper list transcribed at the end of the shift. Every process in this chapter degrades to paper the moment the software is slower than the hands.
Field notes & further reading
- 19 CFR Part 149 — Importer Security Filing — the actual regulation behind "10+2". Section 149.2 gives the timing rules, including which elements are due 24 hours before loading at the foreign port and which are due 24 hours before US arrival; section 149.3 lists every data element and states that the manufacturer, country of origin and HTSUS number must be linked at line-item level. The matching bond text, which carries the $5,000-per-violation liquidated damages figure, is Appendix D to 19 CFR Part 113.
- 46 CFR Part 541 — FMC demurrage and detention billing requirements — section 541.7 sets the 30-calendar-day invoicing deadline and says a late invoice need not be paid; 541.6 lists the mandatory invoice contents; 541.5 says missing information eliminates the obligation to pay; 541.8 gives you at least 30 days to ask for mitigation, refund or waiver. The most directly monetizable regulation in this chapter.
- 19 CFR Part 146 — Foreign Trade Zones (CBP operational rules) — CBP Form 214 admissions, the four zone statuses, the weekly-entry provision at 146.63(c), the 20-day discrepancy report at 146.37, and the inventory-control and audit-trail obligations an FTZ imposes on your ERP.
- International Chamber of Commerce — Incoterms 2020 — the publisher's own summary of all eleven rules, which of them work for any mode of transport, and what changed from the 2010 edition. The full rule book is a paid publication, but this page is enough to work out which term belongs in your supplier contract.
- CBP Decision 25-10 — customs user fees adjusted for fiscal year 2026 — the primary source for the FY2026 Merchandise Processing Fee minimum ($33.58) and maximum ($651.50) per entry. CBP republishes this every summer, so re-check it each fiscal year rather than trusting the number in any book.
- USPS Domestic Mail Manual 123 — prices and dimensional weight — a free, authoritative statement of the dimensional-weight rule and the 139 divisor for retail Priority Mail parcels over 1,728 cubic inches, zones 1–9. Useful when you need to justify cartonization logic to a skeptic.
- NMFTA — National Motor Freight Classification — the standards body's own explanation of freight classes 50–500 and the four characteristics (density, handling, stowability, liability) that set them. Read it before you argue with an LTL carrier about a reclassification.
- 2025 Warehousing Market Report (the Warehousing and Fulfillment Costs & Pricing Survey) — an annual survey of more than 600 warehouses, with reported averages for storage, receiving, pick-and-pack, returns, setup, minimums, account management, pick accuracy, shrinkage and 3PL profit margin. Every rate-card figure in this chapter comes from here. The best free benchmark for judging a 3PL quote, provided you remember it is self-reported, cross-industry, and reissued each year.
- NRF and Happy Returns, 2025 retail returns research — return rate as a share of annual sales (15.8%, or $849.9 billion), online return rate (19.3%), holiday returns (17%) and the finding that 9% of returns are fraudulent. Use it to size your reverse-logistics build.
- NRF National Retail Security Survey, 2023 edition — the source of the 1.6%-of-sales shrink figure for fiscal 2022 and the $112.1 billion total, together with the loss causes retailers themselves report. Look for a newer edition before you quote the number anywhere that matters.
1. Build your own rate card comparison. Take your last twelve months of actual activity — inbound containers, pallet positions held month by month, DTC orders, wholesale cartons, VAS units, returns processed, and price it three ways: against the survey averages in this chapter, against a real quote you request from one 3PL, and against a bottom-up in-house model with a specific building size and headcount. Then compute cost per order for each. Do not stop at the total; separately identify which costs are fixed and which are variable in each option, and state at what order volume the answer flips.
2. Audit one week of your own inventory truth. Pick twenty locations at random, count them blind, and record system quantity, counted quantity, and, for every variance, an investigated root cause from a closed list (mislocation, receipt error, mis-pick, unrecorded damage, unrecorded sample, unit-of-measure error, unexplained). Compute location-level inventory record accuracy. Then write the ledger entries you would post under the reconcile-don't-adjust rule, including transfer pairs where stock was merely mislocated.
3. Price one season's duty twice. Take one style you imported in the last two years. Find the customs entry, the HTS code, the country of origin, and the duty rate that was actually applied. Then find a second entry of the same style from a different date and compare the rate. If they differ, write down what your margin report currently does with that difference, and whether it is right.
When you are done you should have: a defensible fulfillment cost per order with a stated break-even volume, a measured IRA figure for your own operation, a ranked list of your actual shrink causes, a landed-cost figure that survives a tariff change, and a concrete list of the ERP tables and reason codes you now know you need. If your "unexplained" bucket is the largest one, your first engineering task is scan-verification at put-away.