Kind-of-Lost Kind-of-Lost · OR Tools · Staff Scheduler · Warehouse Shift Schedule · Support

Warehouse & Distribution Shift Schedule Maker

Different headcount on every shift and every day — because a distribution centre's demand is a shipping schedule, not a flat requirement.

Warehousing differs from manufacturing in one way that dominates the schedule: the workload is not level. A production line wants the same crew every shift because the line runs at the same rate; a distribution centre has inbound trailers arriving on one pattern and outbound routes leaving on another, a Monday that looks nothing like a Thursday, and a peak season that can double the requirement for eight weeks. So the demand grid — one editable cell per shift per day — is doing most of the work on this page, and getting those numbers right matters more than any parameter you can set.

The second thing that shapes a DC roster is certification. Forklift, reach truck, order picker and powered pallet truck are separate tickets, and a shift with nobody licensed for the reach truck cannot put away a pallet regardless of how many people clocked in. Model each as its own demand with the concurrent flag and give only the certified people a skill row: the flag matters because your forklift driver is one of the bodies on shift, not an extra one, and without it you would be asking for a headcount you do not actually need.

The loaded sample is the three-shift plant — 06:00 / 14:00 / 22:00, which is the same skeleton as a 24-hour DC and the right thing to edit down if you run 24/5 rather than 24/7. If your site closes at the weekend, set the weekend cells in the demand grid to zero rather than deleting the days: the model will schedule nobody, but the rest and consecutive-day rules still see the gap correctly, so a Friday night shift followed by a Monday morning is evaluated with the whole weekend of rest in between.

Peak is where a solver earns its keep here. Rather than rebuilding the roster by hand every November, raise the demand cells for the peak weeks, add your seasonal hires as people whose availability starts on their first day, and re-solve. The permanent staff keep their patterns where the rules allow, and you can see immediately whether the temps you have hired are actually enough — the unfilled-posts table is a hiring plan as much as a scheduling result.

Download this sample (.xlsx)
Or drop your own workbook here — choose a file
Same sheet layout as the samples: shifts, demand all, supply all, skills, one grid per demand and per person, parameters. Download a sample first if you want the template.

Distribution centre scheduling questions

How do I schedule for peak season? Raise the numbers in the demand grid for those weeks and add seasonal staff with availability limited to their contract dates. Nothing else changes — the same roster rules apply, and any shift you cannot cover shows up as an unfilled post rather than a surprise.

Can I require a certified forklift driver on every shift? Yes. Make it a demand with the concurrent flag set, and give a skill row only to certified operators. An uncertified picker then cannot be assigned to it under any cost.

We run 24/5, not 24/7. Put zeros in the weekend cells of the demand grid rather than removing the day columns. Keeping the days means the rest and consecutive-day rules still measure the real gap across the weekend.

Can I separate inbound and outbound crews? Make them two demands and give each worker a skill row for the one they work. If some of your people are cross-trained, give them both rows and the model will move them where they are needed — which is usually the reason to cross-train in the first place.

Does it optimise the warehouse layout too? No. This schedules people. Slotting — deciding which SKU lives in which pick face — is a different optimization problem entirely, and not one this tool solves.

The same solver, other settings

Each of these loads a different worked example and is written for that setting, but they all run the same cross-day engine — if none of them matches yours, start from whichever is closest and replace the data.

How this differs from the other two modes

The staff scheduling optimizer on the home page works in half-hour slots inside a single day: you say how many people you need at 08:00, at 08:30, at 09:00, and it invents shift blocks to match. That is the right model when demand rises and falls through the day — a call centre, a restaurant, a shop — and the wrong model here, because every one of its rules is scoped to one day column. A 19:00–07:00 night becomes two disconnected half-shifts, and no rest rule can span the midnight boundary.

This page replaces the time axis with a shift axis. Your shifts are named blocks with real clock times, and an end time earlier than the start time simply means the shift crosses midnight. Rest between two shifts then becomes arithmetic on absolute minutes across the whole horizon rather than a special case, which is what makes cross-day rules — minimum rest, maximum consecutive days, maximum consecutive nights, no day shift after a night — expressible at all.

The third mode, the shift rotation generator, does not optimize anything: it lays out a named pattern — DuPont, Panama, Pitman, 4-on-4-off — across four crews. Use it when you want a known, published rotation and you do not need the schedule to respond to who is qualified for what, who is on holiday, or which shifts need three people instead of two.

What the solver actually decides

Coverage, skills, availability, pinned assignments and contracted hours are hard — the model physically cannot assign someone to work they are not qualified for or not available for. Coverage shortfall, minimum-hours shortfall, weekend fairness and cross-person equity are soft: each carries a penalty rather than a prohibition. That is a deliberate choice. A roster tool that answers “infeasible” tells you nothing useful; this one always returns a roster and then names the compromises it had to make, in the warnings and the unfilled-posts table.

Why the continuity numbers are on the results page

A roster can be 100% covered and still be unliveable. Everyone in a pay grade earns the same rate and coverage pins the total hours, so rearranging who works when often costs the model literally nothing — the same ward solved twice with staff listed in a different order produced 21 different shifts at an identical objective. Left alone, the solver returns whichever scattered roster it reached first. So the model carries a small penalty on each new block of consecutive days worked, and another on flipping between days and nights, and the results page reports what came out: how many blocks, how long they are, how many are lone single days, and the tightest turnaround anyone actually got. Those are the numbers to argue with, not the objective value.

Common questions

Is it free? Yes — no account, no trial. Your workbook is read to solve the model and not stored.

How many people and days can it handle? Up to 40 people and 31 days per solve. The 28-day hospital ward sample builds roughly 4,300 variables and solves in well under a minute.

What if I want a shift to be someone specific? Put f in that person's grid cell. Forced cells are hard — the solver schedules around them.

Is minimum rest really 11 hours? Only by default. 11 hours is the EU Working Time Directive figure; the US has no federal equivalent and state rules vary, so it is a parameter (MinRestHours) rather than a constant. Set it to whatever your jurisdiction or contract says.

Get an email when we ship updates to this tool. Low volume, unsubscribe anytime.