Restoration Hardware · Global Operations · final project

White Glove delivery optimization for RH

Routing, truck-loading and pricing model for RH furniture deliveries: 11 customers, 18 loads, 5 days, and a case for raising the flat fee.

$299 → $327flat fee needed to break even
Restoration Hardware logo

Tools & methods

  • Python (openpyxl)
  • Excel
  • LibreOffice
  • Google Maps
  • Rome2Rio
  • TravelMath
  • Route optimisation (TSP)
  • Bin packing
  • Claude
  • Perplexity (research)

RH (Restoration Hardware) delivers furniture from its San Francisco warehouse with a "White Glove" service: a three-person crew carries every piece in, stages it and takes the packaging away, for a flat fee of $299 per order. I was asked to plan a week of these deliveries as if I were a summer intern in RH's operations team. I had to decide which customers to visit on which day, in what order, and how to pack the truck, then answer one commercial question: does the $299 fee actually cover the cost?

1. What is the problem statement?

Deliver every assigned order at the lowest total cost, without breaking any operating rule:

  • 11 customers across the Bay Area, from Russian Hill and Presidio Heights to Oakland, Berkeley, Alameda, San Leandro and Sausalito: 134 order lines, 324 items.
  • One truck, one crew: 1,700 cu ft and 7,000 lbs per load, with a driver and two crew members.
  • A fixed working window: 8 AM to 5 PM, Tuesday to Saturday.
  • Handling time that depends on what is being carried: a chair takes 2 minutes to unload, a sofa 4, a bed frame 8, a cabinet or fountain 12.
  • Two cost drivers: crew labour at $104 an hour, and truck operation at $1.205 a mile.

The first finding shaped everything else. The orders add up to 17,713 cu ft and 64,395 lbs, more than ten truckloads. So the problem wasn't just "find the shortest route". It was three linked problems: how to split big orders into safe loads, which loads to run on which day, and what order to drive each day's stops in.

The order volume was 10.4x the truck's capacity, so the question stopped being "which route" and became "which loads, which days, which route".

2. What are the tradeoffs considered?

  • Speed vs space. I built two versions of the plan. One packs the truck as full as possible, so fewer trips (Space-Optimized). The other keeps each day's stops close together, so fewer miles and hours (Speed-Optimized). Fuller trucks sounded efficient, but they force longer, zig-zagging days.
  • Labour dominates cost. Crew time is about 94% of the delivery bill. An extra hour on the road costs far more than a half-empty truck, which is why a shorter day beats a fuller truck.
  • Keeping a customer's order together vs keeping trucks full. Two large orders (Presidio Heights and Alameda) were split across two consecutive days so that each day's truck stayed well used. The cost is two visits for those customers.
  • Exact vs good-enough methods. Brute-force route search checks every possible stop order, which is only practical for small daily route sets like these (up to four stops). For packing, I used a fast rule of thumb (First-Fit Decreasing) instead of solving packing exactly. It's quick, easy to explain and checkable in Excel, but it isn't guaranteed to be optimal.
  • Clustering first, then routing. Grouping customers by area first (SF, Oakland, Berkeley, East Bay, North Bay) makes each day simple to plan. The cost is that it can miss a cheaper plan that mixes regions.
  • Precision vs how crews actually work. Time is rounded to 15-minute blocks (with a ±7-minute rule), matching how crew hours are billed, rather than to the exact minute.

3. What is the solution proposed?

A step-by-step model, built in Python and delivered as an 11-sheet Excel workbook the operations team can change themselves. It runs in three steps.

  1. Pack the truck. I sorted every item from largest to smallest and placed each into the first load with room for both its volume and its weight. Result: 18 loads, each under 1,700 cu ft and 7,000 lbs, averaging 62.3% of the truck's volume.
  2. Plan the days. I grouped nearby customers together: Russian Hill with Presidio Heights, the Oakland Campus Drive stops, Alameda with Berkeley, Alameda with San Leandro, then Sausalito on its own.
  3. Order each day's route. For each day, I tried every possible stop order from the warehouse and back, and kept the shortest. For Wednesday, the naive order ran 42 miles; the model keeps the three Oakland stops together before heading back to SF, which cuts it to 38.

Every day's timeline adds up the same parts: a 23-minute morning check-in, driving at an average of 25 mph, 6 minutes to arrive at each stop, item-by-item unloading and staging, and 8 minutes to leave.

The recommended week (Speed-Optimized):

  • Tuesday: Russian Hill ×2 + Presidio Heights: 5 loads, 12 miles, 7.75 hours, $820
  • Wednesday: Oakland ×3 + Presidio Heights: 4 loads, 41 miles, 7 hours, $777
  • Thursday: Alameda + Berkeley ×2: 4 loads, 37 miles, 7 hours, $773
  • Friday: Alameda + San Leandro: 4 loads, 42 miles, 7.5 hours, $831
  • Saturday: Sausalito: 1 load, 22 miles, 3.5 hours, $391

All 11 customers and 324 items are delivered in five working days. The route covers 154 miles in 32.75 crew hours, for a total cost of $3,591.57. That's $506.37 (12.4%) cheaper than the Space-Optimized plan, which used 4 fewer trips but drove 75 more miles and took 4 more hours.

Should RH review its flat fee? Yes. RH charges per order, not per truckload. A customer who needs three truckloads still pays one $299 fee, so the right number to compare is cost per customer ($326.51), not cost per load ($199.53). At $299, this week loses $302.57 (revenue $3,289 against $3,591.57 in cost), or $27.51 per customer. The fee needs to rise to about $327, around 9.4%, just to break even. Better still would be to tier it by size, so a three-load order stops being subsidised by small ones.

4. Any other improvements I could have done?

  • Solve the whole problem at once. Instead of cluster, then pack, then route, I could model it as one vehicle-routing problem with capacity limits (in a tool such as OR-Tools, or as a mixed-integer model), so loads, days and routes are chosen together.
  • Load safely, not just by volume. I could add stacking rules, fragile items, weight balance and unload order (last on, first off), so the loads are also easy to unpack.
  • Real traffic and customer windows. I could replace the flat 25 mph with live traffic-based drive times, and add each customer's preferred delivery window.
  • Put a cost on splitting an order across days. I could add a penalty for splitting a customer across two days, and show RH the trade-off between cost and customer experience.
  • More trucks, right-sized trucks. I could test two trucks running at once to finish sooner, and a smaller van for tiny orders. The Berkeley order was only 139 cu ft.
  • Stress-test the price. I could run sensitivity checks on wages, fuel and order mix, so the fee recommendation holds up in a busy week as well as a quiet one.

Want the story behind a project?

Grab my CV, or reach out and I'll walk you through the decisions and the numbers.

All projects