The engine

A solver, not a calendar.

Most scheduling software takes bookings against slots a human already worked out. This works out the slots. It is a constraint solver — Google's OR-Tools CP-SAT — searching for the arrangement that places the most people without breaking a single rule.

Rules it will never break

Hard constraints are not preferences and they are not weighted. If a schedule would violate one, that schedule does not exist as far as the solver is concerned. There is no slider that turns these off, because a timetable that double-books a room is not a cheaper answer — it is a wrong one.

  • Nobody is in two places at once. An attendee is never placed in overlapping sessions.
  • An event never overlaps itself. If it runs three times a week, those three sessions are distinct.
  • Availability is absolute. A person is only ever placed inside the windows they gave you — and no windows at all means available always, not unavailable.
  • No instructor is ever double-booked, and none is scheduled outside their availability.
  • No room is ever double-booked, and a room is never given an event bigger than it holds.
  • Session capacity is never exceeded.
  • A fixed-time event keeps its clock time. The solver only chooses which day.
  • An equivalence group places each attendee in exactly one of its events — never none, never two.
  • A pinned session stays exactly where you pinned it.

Preferences you actually control

Everything that is a matter of taste rather than physics is a weighted preference, and you set the weights before each run. Six sliders, each 0 to 100. Turn one to zero and the solver stops caring about it entirely.

PreferenceDefaultWhat it does
Maximise enrolment fulfilment100Place as many enrolled people as possible. The reason anyone runs this at all, so it starts at the top.
Honour high-priority enrolments80An enrolment marked high priority counts double when the solver has to choose between two people for one seat.
Balance session attendance60Spread people evenly across the sessions of an event rather than filling the first one and leaving the last half empty.
Prefer distinct days50When an event runs several times a week, spread those sessions across different days.
Prefer attendees’ starred times40Attendees can star the windows they would rather be in. Availability is a hard rule; a star is a wish.
Minimise instructor back-to-back30Leave a gap between the sessions one instructor teaches, instead of stacking them nose to tail.

Why the weights cannot betray you

The objective is strictly tiered. Placing one more person outranks every soft preference added together, and the preferences in turn outrank the tie-breaks. So you can set the weights however you like without ever discovering that the solver dropped somebody from the timetable to win a nicer instructor gap. It cannot. The arithmetic forbids it.

Pin what works. Re-run the rest.

Almost every run is a second run. You look at the week, three sessions are exactly right, the rest is not. Pin the three. The next run treats them as fixed — day, time, instructor and room — and rearranges everything else around them.

Pins carry themselves forward: a run that honours a pin marks its own output pinned too, so you can pin a little, run, pin a little more, run again, and converge without re-pinning from scratch each time.

Small change in, small change out

The awkward truth about optimisers is that they are unstable. Add one attendee, re-run, and you can get a completely different timetable because the new one scores a fraction of a percent better. Mathematically correct; socially disastrous, because forty people already moved their Tuesday.

A run can be anchored to the previous one. Sessions, instructor assignments and room assignments that can stay where they were are rewarded — but at the weakest tier of the objective, below every real preference and far below placing people. Stability is a tie-break, never a trade. The previous answer is also handed to the solver as a starting hint, so it spends its time improving your week rather than rediscovering it.

Four answers, and they mean different things

"It didn't work" is not a useful result. Every run comes back as one of four distinct states, because the right next move is different for each.

Best possible
Proven optimal. There is no better arrangement under the constraints and weights you gave it — not "none was found", none exists. Stop looking.
Stopped at the time limit
A good schedule, found and kept, plus the optimality gap: an upper bound on how much a longer search could still improve it. A 2% gap tells you to publish; a 30% gap tells you to run it again.
Ran out of time
No schedule found yet. This is emphatically not the same as impossible — it usually means the problem is large or tightly constrained. Loosening one window is often enough.
No schedule possible
The hard constraints genuinely contradict each other. Something has to give, and the diagnosis below tells you what.

The search budget is derived from the size of the model rather than being a flat timer, so a small project answers quickly and a large one is given the time it actually needs — roughly twenty seconds at the low end, a couple of minutes at the top.

It tells you why, not just no

Every person the solver could not place comes back with a categorised, readable reason rather than a shrug:

Not available
Their windows do not overlap any time this event could run.
Full
Every session of the event was already at capacity.
Clashes
Placing them here would collide with another event they are enrolled in — and it names that event.
No slot fits
The event has no candidate time that satisfies its own day, window and duration rules.
Mixed
More than one of the above applies across the event’s sessions.

And it stops you before you waste a run

Some problems are visible before the search starts, so they are checked first. An attendee with no availability at all. An event needing more weekly hours than its window contains. More sessions per week than can fit without overlapping. Demand that exceeds total capacity. Instructor and room clashes.

Most of these are warnings you can acknowledge and run through anyway. Two are hard stops — an event that requires an instructor when no eligible instructor is ever free, and the same for rooms — because those cannot produce a schedule and the run would only be a slower way of finding that out. Each one names the event and the fix.

The shapes most tools cannot express

Attend one of these
An equivalence group is a set of interchangeable events — three sittings of the same class, four practical groups. Enrol someone in the group and the solver picks whichever member fits their week. Exactly one, guaranteed.
Attend some of these
A partial enrolment says "any two of the four sessions". You are not forced to choose between all and nothing.
All or nothing, when it matters
And when partial placement is not acceptable, one run flag makes every enrolment all-or-nothing instead.
Fixed times, free days
An event that must start at 18:00 but could be any weekday is a first-class case, not a workaround.
Eligibility, not just availability
Instructors and rooms carry lists of what they are allowed to take. A room also has to be big enough. Event groups fan that eligibility out across every event in them at once.

Then compare the runs

Drafts accumulate; you choose what to publish. Any two runs can be put side by side, and the difference is reported the way a human would describe it: this session moved (one change, not a deletion and an addition), this person gained a place, this person lost theirs, this instructor now teaches a different week. Attendees and instructors are diffed separately, because they need different conversations.

That same difference drives who gets emailed — only the people whose week actually changed. And the whole loop, in order, is on how it works.

What the engine does not do

  • No manual drag-and-drop override. Every placement comes from a run, which is the only way the result stays provably conflict-free. Pinning and fixed times are how you steer it.
  • Weekly repeating patterns only. There is no multi-week rotation, no dated one-off roster, no exam-timetable mode.
  • No labour rules. Maximum hours, overtime, break law and required coverage per slot are not modelled.
  • No cover or substitution flow yet. Re-running with the absent instructor marked unavailable is the current answer.

See it on your own timetable.

14 days, no card. Everything on this page works on the trial and on every paid plan — the tiers differ only by how many attendees and events you can hold.