Assignment optimization
How On-Call Optimizer chooses the best assignment, the optimization rules it balances, and how to weight them.
On-Call Optimizer doesn’t rotate through members in a fixed order. Each time it creates an assignment, it searches for the combination of members and shifts that best satisfies a set of optimization rules: fair balance, sensible shift spacing, member availability and hour limits. You choose how much each rule matters with the Priority setting on a template’s Settings tab.
This page explains how the search works, what each rule does, and how rule weights decide between them.
How the optimizer works
On-Call Optimizer uses constraint programming to find the best assignment. It works in three steps:
- Variables. Every possible choice is a yes/no variable for a (shift, role, member) combination. A schedule with 5 members and 7 shifts that each need a primary assignee has 35 variables.
- Fixed requirements. Some things always hold. Each role in a shift that needs an assignee gets exactly one member. Only assignable members, or members of the shift’s assignment group, can fill it. Named assignees, Last primary and Last secondary are kept as configured. These come from the template’s shift configuration. Giving one member two overlapping shifts is so costly that it practically never happens.
- Rules. Each optimization rule adds a cost for situations it wants to avoid, such as uneven shift counts or a member on call during a blocked period, and a negative cost (a bonus) for situations it wants, such as a member on call when they asked to be. Each cost is multiplied by its rule’s weight.
The optimizer then picks the assignment with the lowest total cost. Over the long term this keeps the schedule balanced; in the short term it respects each member’s availability information.
Best member
Best member (written BEST_MEMBER in the example configs) is the assignee you
choose in a shift to let the optimizer decide. The best member for a shift is whoever the lowest-cost assignment puts
in it. Best member from group does the same, limited to one assignment group.
“Best” doesn’t mean “perfect”. When rules pull in different directions, the best overall assignment may give a member two close shifts or ignore a preference, because every alternative scores worse in total.
Rules
| Rule | Purpose |
|---|---|
| Balance assignment load | Distribute shifts fairly across all members |
| Shift distribution | Control how shifts are spaced or grouped for each member |
| Respect availability information | Honour member preferences and blocked periods |
| Hour limits | Limit on-call hours within any period of a set length |
Balance assignment load
The balance rule spreads shifts fairly across the members of the schedule. It calculates a target value for each member which takes into account when they joined the schedule and any configured per-member shift allocation percentages.
The target for each member is tracked at both the shift type and overall levels, to prevent one member being assigned a disproportionate share of less desirable shifts while also keeping the overall share of shifts assigned in balance.
The balance rule penalizes assignments by summing, for each pair of members, the difference in how many shifts from their target each member is (e.g. two members who are both at their target will have a difference of zero, even when their targets differ). The higher the sum, the more imbalanced (distance from target) the members of the schedule are.
For more detail on how balance is calculated and displayed, see schedule balance.
Shift distribution
The shift distribution rule controls how each member’s shifts are spaced relative to one another within the schedule.
Distribution modes
Two distribution modes are available. Choose the schedule’s default in the Distribution setting on a template’s Settings tab (Spread out across rotation or Cluster). The Distribution and Hour limits settings are only shown where shift distribution is enabled for your schedule.
Spread: shifts are spaced as far apart as possible. This is the default, and it suits teams that want recovery time between on-call shifts. When spread mode is active, On-Call Optimizer penalizes shifts that are closer together than the expected spacing for the schedule, with a higher penalty for truly consecutive shifts and a progressively lower penalty as the gap increases out to the expected spacing.
Cluster (consecutive): shifts are grouped together into blocks. This mode is useful for teams with short shifts (e.g. daily) to allow for assignment flexibility, but which still prefer to concentrate on-call duty into fewer, longer stretches rather than disconnected single days. When cluster mode is active, On-Call Optimizer favours assigning adjacent shifts to the same member rather than spreading them across the team.
When cluster mode is active, a companion hour limit is added to the schedule to provide an upper bound on the length of consecutive assignments.
Per-member preferences
When allow member overrides is turned on under Distribution on the template’s Settings tab, individual members can override the schedule’s default distribution mode with their own preference. A team can mix the two to accommodate differing individual desires: some people want blocks of on-call, others want their shifts spaced out.
Each member’s choice is set in the Shift distribution column of the template’s Members tab: Schedule default, Spread, or Cluster with an optional cap such as “up to 48h in any 168h period”.
Respect availability information
The availability rule makes On-Call Optimizer use the availability information provided by each member when generating assignments.
Availability information is provided by members through their connected calendars and indicates periods where they are blocked (unavailable) or have a preference to be assigned.
Blocked periods
When a member marks a period as blocked, On-Call Optimizer applies a penalty to any assignment that would place them on call during that time. The penalty for a block is large relative to the other rule penalties and bonuses, so blocked periods are respected as strongly as possible: a member is only assigned to a blocked shift as a last resort, when no better assignment exists.
Preferred periods
When a member marks a period as preferred, On-Call Optimizer gives a small bonus to assignments that place that member on call during the preferred time. Preferences are hints rather than requirements, and the size of the bonus means they are honoured only when they don’t conflict with more important objectives like balance or blocked periods.
The strength of preference bonuses is also modulated by each member’s current assignments relative to their target. Members who are ahead of their target (assigned more shifts than expected) have their preference bonuses reduced, while members behind their target see them strengthened, so preferences don’t undermine balance over time.
Overlap weighting
The size of the penalty or bonus applied to the assignment for each piece of availability information that overlaps with a shift assigned to a member is weighted according to the proportion of the shift that is overlapped.
Hour limits
An hour limit caps the total on-call hours a member can be assigned within any period of a set length. As well as providing an upper bound for the cluster distribution mode, hour limits can be useful for enforcing workload policies, supporting legal requirements around maximum working hours, or managing cross-timezone schedules where different team members have different workload constraints.
Set them under Hour limits on a template’s Settings tab. Each limit reads “up to Xh in any Yh period”: X is the most hours on call you want a member to have, and Y is the length of the period they are counted over. For example, “up to 40h in any 168h period” allows 40 hours in any 7 days. Click Add hour limit to add one (up to 10), or the trash icon to remove one.
When a potential assignment would cause a member to exceed the hours in any such period, the optimizer applies a penalty proportional to the excess. This is a soft constraint: On-Call Optimizer avoids exceeding the target but may do so if no better alternative exists.
Rule weights
Rules often pull against each other: perfectly balanced shifts might mean ignoring a member’s preference. Each rule’s weight sets how much it counts when that happens, so each schedule can decide which assignments On-Call Optimizer considers best.
Weights are relative, not absolute. What matters is the ratio between weights, not their individual values. Doubling one rule’s weight has the same effect as halving every other rule’s weight: it makes that rule comparatively more important.
Terminology
Each rule assigns a cost to each relevant situation it finds in a potential assignment: for example, an imbalanced shift count, a closely spaced pair of shifts, or a member assigned during a blocked period. Most costs are penalties for undesirable situations. Some are negative, bonuses that encourage desirable ones, such as a member assigned to a shift they preferred. The total cost of an assignment is the sum of all its costs, and On-Call Optimizer selects the assignment with the lowest total.
Each type of cost has a base value that reflects its inherent severity. The base values set a priority order between costs, within and across rules, that applies even when all rule weights are equal. Rule weights then multiply these base costs: increasing a rule’s weight amplifies all of its costs, shifting On-Call Optimizer’s attention towards that rule’s objectives.
Example costs
The real base values are tuned for different schedule patterns, but their relative sizes look roughly like this:
| Situation | Illustrative cost |
|---|---|
| Member assigned during a blocked period | Large (more than 2), so it happens only as a last resort |
| Each shift a member is above or below their balance target | 1 |
| Consecutive shifts for one member (spread mode) | 0.3 |
| Member assigned during a preferred period | −0.5 (a bonus) |
With equal weights, this gives On-Call Optimizer its default behaviour: share shifts fairly, strongly avoid blocked periods, and honour preferences when it can.
Priority presets
Priority presets are ready-made weights for the usual tensions between rules, so a schedule can favour one goal over another. Choose a preset in the Priority setting on a template’s Settings tab. Presets are the recommended way to configure rule weights without adjusting individual values.
When a preset is selected, the weights for all rules are set to the values defined by the preset. The active preset is shown in the Priority selector, which shows Custom if the current weights do not match any available preset.
The following presets are available:
Default: all rules are weighted equally. This provides an even weighting across balance, shift distribution and availability preferences, and is a good starting point for most schedules.
Balance assignment load: increases the weighting of the balance rule relative to other rules. This suits schedules where fair distribution of shifts is the main concern, and On-Call Optimizer should prioritise closing the gap between members even when that means placing a member on call during a less preferred time or with less ideal shift spacing.
Respect availability information: increases the weighting of the availability rule relative to other rules. This suits schedules where member availability is the main concern, and On-Call Optimizer should honour blocked periods and preferences even if that leaves a temporary imbalance between members.
Distribute shifts: emphasises spacing or grouping each member’s shifts, using the schedule default and their own preference. This suits schedules where that spacing is the main concern.
Custom weights
When the presets don’t match your requirements, choose Custom in the Priority setting. This shows a slider for each rule, so you can set its weight directly.

Weights use a scale from 0 to 10:
- 0: the rule is ignored entirely. On-Call Optimizer doesn’t consider this objective at all.
- 1: the default importance. The rule participates in optimization at its baseline level.
- 2 to 10: increasing importance. Higher values make On-Call Optimizer favour this rule more strongly relative to others.
Per-assignment customization
The priority weights can be adjusted for a single custom assignment without changing the template. After creating the assignment, open its Configuration tab and click Customize (or Edit customizations) to change its Priority. This is useful for one-off situations, such as generating an assignment during a period with unusual availability constraints.
Reviewing an assignment against the rules
An assignment’s Evaluation tab shows how it scores against these rules. The Penalty section has an Overall value and one value per rule (for example Balance, Shift distribution and Availability). Higher values are worse; negative values mean preferences were honoured. Point at a value for a description of the rule. See Assignments for more about assignment pages.
Assignments created before their schedule had a Priority setting were scored by the earlier version of the optimizer, which used fixed weights for the same goals. Their assignment page shows an Older algorithm badge, and their evaluation shows raw values rather than per-rule penalties.