Kind of Lost Kind of Lost · OR Tools · Staff Scheduler · Security Guard Schedule · Support

Security Guard Schedule Template (Free, Editable)

A ready-made template — one post, two shifts, seven guards, three weeks — or rebuild it your way with weekend fairness and workload equity switched on.

The template above is a worked 21-day roster for one post, two shifts and seven guards — open it, and the schedule is already solved. The rest of this page is what the tool does with it and why guard rosters are their own problem.

Guard scheduling is the small-team version of the 24/7 problem, and small is what makes it awkward. A post that needs one guard on days and one on nights, every day, is 42 shifts over three weeks. Seven guards covering that means six shifts each, and there is almost no slack — one person's holiday or one over-tight rest rule and a post goes dark. That is a very different situation from a hospital ward with sixteen staff, where the solver has room to trade.

Because the team is small, fairness stops being a nicety and becomes the actual complaint you will field. The sample on this page is the only one on the site with WeekendFairnessPenalty and EquityPenalty turned on. The first spreads Saturday and Sunday shifts across the team instead of parking them on whoever the solver reached first; the second flattens total hours between guards. Both are soft — they lose to coverage, because an unguarded post is worse than an unfair Saturday — but they change the roster you get out noticeably, and you can see the effect directly in the per-guard hours and night counts in the results table.

Weekend rules need one thing from your data to work at all: readable day labels. If the columns are dates or weekday names the model knows which columns are Saturday and Sunday; if they are opaque strings like “D1, D2, D3” it cannot, and rather than guess it turns the weekend rules off and says so in the warnings. That warning is worth reading — a silent guess here would produce a roster that looks fair and is not.

The other number to watch on a small team is continuity. With seven guards and 42 shifts, the default clustering penalty took the sample from 27 lone single days worked down to 3 — which is the difference between a guard working a recognisable block and a guard being called in on scattered days across three weeks. Coverage was identical either way, so nothing but that penalty decided it.

Download the Security Guard Schedule template (.xlsx)
A worked roster you can print or adapt, with the input sheets behind it — edit those and drop the file back in below to re-solve it as your own.
Download template
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. The template above has all of them filled in.

Guard-scheduling questions

How small a team can this handle? There is no minimum, and the interesting failures happen at the bottom end. With a genuinely impossible team — one person, two shifts a day — it will not pretend: it returns the roster that rest rules allow and lists every post it could not fill.

Can I give different guards different sites or clearances? Yes — one demand per post or clearance level, and the skills sheet decides who can stand where. Only listed guards can be assigned, and it is structural rather than a penalty, so no combination of costs will slip an uncleared guard onto a cleared post.

How does it handle holiday and time off? Leave the cell blank in that guard's grid for the day and shift they are away. Unavailability is hard, so the solver will take a shortage before it books someone who is off.

Is weekend fairness guaranteed? No, and it should not be. It is a penalty, not a constraint — if the only way to cover Sunday night is the guard who worked last Sunday night, the model covers the post. The weekend counts in the results tell you when that happened so you can settle it yourself.

Can I print the roster for the guardhouse wall? Yes — the print view drops the site chrome and prints the person-by-day grid on its own, and there is an Excel export next to it.

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

Skills, availability, pinned (f) assignments, maximum hours and days, minimum rest and the consecutive-day and consecutive-night caps are hard — the model physically cannot assign someone to work they are not qualified for, not available for, or not rested for. Filling every post, reaching each person's minimum hours, 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, so a post the rules cannot fill comes back as an unfilled post, named in the warnings and the unfilled-posts table, not as a failure. The one way to get “infeasible” is hard rules that contradict each other — almost always an f cell that breaks a rest, consecutive-day or maximum-hours rule.

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 kept afterwards. We do cache some data on the server to speed up responses and keep an anonymous count of runs.

How many people and days can it handle? Up to 60 people, 42 days (six weeks), 12 shifts and 12 demand streams 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.