Kind-of-Lost Kind-of-Lost · OR Tools · Staff Scheduler · Nursing Home Schedule · Support

Nursing Home & Care Home Staff Scheduler

Long-term care runs 24/7 on a thinner margin than a hospital ward — this builds the rota and shows you exactly where the margin runs out.

Long-term care looks like hospital rostering and behaves nothing like it. A ward's demand comes from acuity and turns over constantly; a care home's comes from a resident census that barely moves month to month, which sounds easier and is not, because the staffing is set close to the legal minimum and stays there. When a hospital ward is one nurse short it flexes. When a care home is one aide short on nights, the shift is below ratio and there is nobody to pull from.

That is the real scheduling problem here, and it is a ratio problem rather than a headcount one. Most jurisdictions express minimum staffing as hours per resident day, or as a required licensed nurse presence at all times, rather than as “four people on nights.” You do the conversion once — census times required hours, divided by shift length — and enter the result as the number of people that shift needs. From then on the model treats it as hard demand, and any shift it cannot fill shows up in the unfilled-posts table instead of quietly becoming somebody's problem at 03:00.

Two constraints bite harder in long-term care than anywhere else on this site. The first is the licensed-nurse requirement: in most homes exactly one RN or LPN must be on duty at all times, drawn from a small pool, which is precisely the concurrent demand pattern the charge-nurse stream uses in the loaded sample — that nurse is also one of your care staff, not an extra body. The second is turnover. CNA turnover in long-term care is high enough that the roster you build in month one is not the roster you have in month three, so treat the per-person availability grid as the thing you maintain, and re-solve rather than patch.

The sample loaded here is the hospital ward — two 12-hour shifts, a licensed-nurse stream and a care-assistant stream, which is structurally the same shape as a care home on twelves. If your home runs the more common day / evening / night split on eights, change the three rows in the shifts sheet to 07:00–15:00, 15:00–23:00 and 23:00–07:00 and the rest of the workbook carries over unchanged.

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.

Care home rostering questions

Can it enforce a minimum staffing ratio? It enforces a headcount per shift, which is what a ratio becomes once you have done the census arithmetic. Work out how many staff your ratio requires on each shift, put that number in the demand grid, and the model treats falling short of it as a costed failure rather than an option. It will not recalculate the ratio for you when your census changes — that is your number to update.

How do I make sure a licensed nurse is always on? Make it a separate demand with the concurrent flag set, and give only your RNs and LPNs a skill row for it. The model then cannot produce a shift without one, and because the demand is concurrent that nurse still counts toward your general care headcount rather than sitting on top of it.

What about agency and float staff? Add them as people with availability only on the days they are actually offered to you, and give them a higher cost_per_hour than your permanent staff. The solver will then use them last — only where a permanent member of staff cannot legally or contractually cover the shift — which is usually the behaviour you want and is hard to hold to by hand.

Our staff work double shifts. Can I allow that? Yes, but do it deliberately. Raise max_hrs_day to 16 or 24 for the people it applies to, and remember that minimum rest is still enforced afterwards, so a double on Tuesday pushes their next possible shift further into Wednesday. If the roster gets worse when you allow doubles, that is the rest rule telling you something true.

Is this different from the nurse scheduling page? Same engine, different starting assumptions. That page is written for an acute inpatient ward with an RN-heavy skill mix and acuity-driven demand; this one is written for a fixed census, a minimum-staffing floor and a single licensed nurse on nights. Use whichever description matches your building.

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.