Skip to main content

Schedule Generation Algorithm

This document explains how Pivot automatically generates employee shift schedules when a manager clicks "Generate."


What It Does

The algorithm takes a list of employees, a set of positions that need coverage, and a week — then fills shifts automatically based on employee availability, company rules, and position priorities. Any shifts it can't fill become "open shifts" that managers can assign manually.


Inputs

When a manager triggers generation, the system uses the following information:

  • Selected positions: which positions the manager wants to generate shifts for
  • Week: the target week to generate
  • Company shift structure: how each day is divided into periods (morning/evening), with defined shift slots and staffing requirements per position
  • Employees: active employees with their assigned positions, weekly availabilities, personal days off, max hours per week, max days per week, and priority/seniority
  • Availability overrides: if an employee has submitted updated availability for the current or upcoming week, the latest submission replaces their base availability
  • Recurrent patterns: repeating shift templates that employees follow weekly or bi-weekly (e.g., "every Monday morning")
  • Existing schedule: any shifts already placed (from a previous generation or manual edits) — these are preserved
  • Closed days: days the business is closed (no shifts generated)
  • Company settings: generation mode (seniority vs equal distribution), shift splitting preference, shift priority ordering, break rules

What Gets Cleared vs Preserved

Before the algorithm runs, the existing schedule is cleaned:

  • Cleared: all previously generated (non-manual) shifts for the positions being generated — the algorithm starts from a clean slate for those positions
  • Preserved: manually placed shifts (isManual) for those positions — manager edits are never auto-removed
  • Preserved: all shifts (generated or manual) for positions NOT being generated — untouched
  • Removed: shifts belonging to archived, deleted, or inactive employees (unless in already-published positions)

The 4-Phase Process

Each phase runs twice: first for regular shifts, then for on-hold shifts. On-hold shifts represent tentative staffing needs that may or may not be activated. Regular shifts always take priority.

Phase 1 — Recurrent Shifts

Employees can have recurring weekly templates (e.g., "Monday morning at Position A every week"). The algorithm places these first since they represent committed patterns.

How it works:

  • Positions are processed in priority order, then sub-positions within each position
  • For each employee who has a recurrent template for a given position, the algorithm finds the matching shift slot in the schedule
  • If the employee passes the eligibility checks, the shift is assigned and the slot is marked as filled

What is checked:

  • Employee has availability that day
  • No day-off conflict
  • Shift fits within the employee's declared availability hours
  • Employee has enough weekly hours remaining (max hours per week)
  • Employee hasn't reached their max days per week
  • No time overlap with other assigned shifts
  • Employee doesn't already have 2 shifts on this day

What is NOT checked:

  • The 6th day rule and the company-wide daily hours cap do not apply to recurrent shifts. If an employee has recurrent templates on 6 days and their max days per week allows it, all 6 will be assigned.

Skipped recurrent shifts fall through to Phase 2: if a recurrent shift cannot be placed for an employee (e.g., they are unavailable that day or have an approved time off), the shift slot remains unfilled and another eligible employee can pick it up during Phase 2 — Regular Shift Assignment. The recurrent template does not "reserve" the slot.

If an admin marks a template week as "Complete" in the Fixed Schedule UI, the employee is treated as template-only for that week — Phases 2, 3, and 4 skip them entirely, and only their recurrent shifts from Phase 1 are used. If the recurrent shifts can't be placed (e.g., the employee is not available on those days), they are silently skipped and the employee may end up with fewer shifts or none at all — there is no fallback to regular assignment.

Phase 2 — Regular Shift Assignment

This is the main phase. It fills remaining demand after recurrent shifts are placed. All eligibility checks are enforced (see Employee Eligibility below).

Two company settings control how this phase behaves: Generation Mode and Shift Priority. The shift priority is evaluated first — it determines the overall strategy. The generation mode then determines employee ordering within that strategy.

Settings Reference

Generation Mode (set in Company Settings → Schedule):

ValueBehavior
Equal Distribution (default)Shifts are distributed as evenly as possible across all employees. The algorithm aims to ensure every employee receives at least one shift before anyone gets a second. When two employees have the same number of shifts, the one with higher sub-position priority (set in Employees module) gets the next shift.
SeniorityEmployees are processed in position-level priority order (set in Employees module). The highest-priority employee fills as many days as possible (up to their max days per week) before the algorithm moves to the next employee. Employees at the bottom of the list may not receive any shifts if demand is already met.

Shift Priority (set in Company Settings → Schedule):

ValueBehavior
Longer shifts first (default)Within each position/sub-position, the longest shift slots are filled before shorter ones. The generation mode determines the full assignment strategy (see below).
Period startAll unfilled shift slots across all positions are collected into a single flat list, sorted by proximity to the morning/evening period boundary. The generation mode only affects employee ordering (see below).
ChronologicalAll unfilled shift slots across all positions are collected into a single flat list, sorted by time of day (earliest first). The generation mode only affects employee ordering (see below).

How the Settings Combine

The shift priority setting is evaluated first. When it is Period start or Chronological, both generation modes use the same flat-list strategy (only the employee ordering differs). When it is Longer shifts first, the generation mode determines the full assignment approach.

Shift PriorityGeneration ModeStrategy
Longer shifts firstEqual DistributionRound-robin by position (see below)
Longer shifts firstSeniorityFill by employee rank (see below)
Period startEqual DistributionFlat list — employees sorted by fewest shifts first
Period startSeniorityFlat list — employees sorted by position-level priority
ChronologicalEqual DistributionFlat list — employees sorted by fewest shifts first
ChronologicalSeniorityFlat list — employees sorted by position-level priority

Flat List Strategy (Period Start or Chronological + any generation mode)

Used when shift priority is Period start or Chronological, regardless of generation mode.

  1. Collects all unfilled shift slots across all positions into a single flat list
  2. Sorts them by the chosen criteria:
    • Period start — shifts closest to the morning/evening period boundary come first
    • Chronological — shifts are ordered by time of day (early morning first)
  3. Walks through the sorted list one shift at a time
  4. For each shift, finds all eligible employees and sorts them:
    • Equal Distribution: by fewest total shifts first (ties broken by sub-position priority)
    • Seniority: by position-level priority (highest seniority first)
  5. Assigns the first eligible employee
  6. The shift list is not re-sorted after each assignment — the shift order stays fixed

Round-Robin by Position (Equal Distribution + Longer Shifts First) — default

Used when shift priority is Longer shifts first and generation mode is Equal Distribution. This is the default combination.

The goal is fairness — every employee gets roughly the same number of shifts, aiming to ensure that every employee receives at least one shift before anyone gets a second.

  1. Positions are processed in priority order, then sub-positions within each position
  2. For each sub-position, eligible employees are sorted by fewest total shifts first (ties broken by sub-position priority)
  3. The algorithm tries each day and each shift slot (longest shifts first within each day)
  4. As soon as one shift is assigned, the entire process restarts — employees are re-sorted so the one who just received a shift moves down the list, giving others a turn
  5. This continues until no more assignments can be made

Fill by Employee Rank (Seniority + Longer Shifts First)

Used when shift priority is Longer shifts first and generation mode is Seniority.

  1. Positions are processed in priority order
  2. Employees are processed in position-level priority order (highest priority first)
  3. Each employee fills as many days as possible (up to their max days per week) before the algorithm moves to the next employee
  4. Within each day, the employee's preferred sub-positions are tried first (if set), then remaining sub-positions by default priority
  5. Senior employees get full preference regardless of balance — employees at the bottom of the list may not receive any shifts if demand is already met

Phase 3 — Swap Optimization

After initial assignment, some shifts may remain unfilled even though coverage could improve with rearrangement. Only runs in Equal Distribution mode (skipped for Seniority).

The swap phase looks for situations like:

  1. Shift X still needs someone
  2. Employee A could work Shift X but is already assigned to overlapping Shift Y
  3. Employee B is found who could take Shift Y instead
  4. Solution: move A from Shift Y to Shift X, give Shift Y to B — now both shifts are covered

Rules:

  • Recurrent shifts are never swapped — only regular shifts can be moved
  • Both employees must remain eligible after the swap (hours, availability, time conflicts)
  • The process repeats (up to 500 passes) until no more beneficial swaps are found

Max days per week is enforced — a swap cannot move an employee beyond their preferred max days per week.

Phase 4 — Shift Splitting (Optional)

Only runs if shift splitting is enabled in company settings. Targets unfilled shifts of 6+ hours.

For each unfillable shift:

  • Split it into two halves (e.g., a 7-hour shift becomes 3.5h + 3.5h, minimum 3 hours per half)
  • Find two different employees who can each cover one half
  • If both halves find an eligible employee, assign them

If no valid split is found, the shift remains unfilled.


Employee Eligibility

For each shift, an employee must pass all of these checks:

CheckDescription
ActiveEmployee is not archived
Has positionEmployee is assigned to this position and sub-position
AvailableMarked as available on this day of the week
No day-offNo personal day-off on this date (or the day-off hours don't overlap with the shift)
Max days per weekHasn't reached their preferred max days per week
6th day ruleWon't be scheduled on a 6th distinct day in the week
Hours remainingHas enough weekly hours remaining for this shift
Time windowShift fits within the employee's declared availability hours (with a small tolerance on start time)
Daily hours capWon't exceed the company's max hours per day
Max 2 shifts/dayDoesn't already have 2 shifts on this day
No time overlapNo conflict with other assigned shifts (minimum gap between shifts is respected)
No recurrent conflictShift doesn't clash with a recurrent template that hasn't been placed yet

Not all checks apply equally across all phases — see the notes in each phase above.


Open Shifts

After all 4 phases, any shift slot that still needs employees becomes an open shift. These appear in the schedule for managers to manually assign an employee.


Availability Overrides

Employees can submit availability change requests for future weeks via the mobile app (e.g., "starting next week I can only work mornings"). Each request includes an effective date — the week from which the new availability should apply.

These requests go through the Requests module and must be approved by a manager before they take effect. Once approved, the new availability is stored as a pending override with the specified effective date. It does not immediately replace the employee's base availability.

When generation runs:

  • The system reads all approved pending overrides with an effective date up to the end of the target week
  • For each employee, it picks the most recent approved override
  • If found, it replaces the employee's base availability for this generation — including day-by-day availability windows, max hours per week, and max days per week

Separately, a daily cron job (runs at 5 AM) checks all pending overrides. When an override's effective date has arrived, the cron copies it to the employee's base availability and removes the pending entry. From that point on, the override becomes the employee's permanent availability until changed again.


How Hours Are Tracked

Each employee has a weekly hours budget. After every shift assignment:

  1. The shift length is calculated
  2. If break exclusion is enabled, the system adjusts for break thresholds (e.g., shifts over 5 hours include a 30-minute unpaid break)
  3. The adjusted hours are subtracted from the employee's remaining weekly budget

Once the budget reaches zero, the employee is no longer eligible for additional shifts.


Company Settings

These are company-wide settings configured by administrators. They apply to every schedule generation.

Generation Behavior

SettingDescription
Generation modeEqual distribution (default) — shifts are distributed more evenly, with the algorithm aiming to ensure that every employee receives at least one shift. Priority is set by sub-position in the Employees module and used as a tiebreaker. Seniority — the algorithm prioritizes filling each employee's maximum days per week according to a position-level priority order set in the Employees module. Senior employees fill their entire schedule before anyone else gets shifts. Employees at the bottom of the list may not receive any shifts.
Shift priorityControls the order in which shifts are filled. Applies to both Equal Distribution and Seniority modes. Longer shifts first (default) — big shifts get assigned before small ones; each mode uses its own assignment strategy (see Phase 2). Period start — shifts closest to morning/evening boundaries are filled first; uses a flat-list strategy regardless of generation mode. Chronological — shifts are filled in time order throughout the day; also uses the flat-list strategy.
Shift splittingWhen enabled, any unfilled shift of 6 hours or longer can be split into two halves (minimum 3 hours each) and assigned to two different employees. Disabled by default.

Shift Structure (Day Structure)

The company defines how each day of the week is organized:

SettingDescription
Morning/evening periodsEach day is divided into a morning period and an evening period, each with a defined start time (e.g., morning starts at 10:00, evening starts at 16:00). These boundaries determine which shifts belong to which period.
Shift slotsWithin each period, the company defines specific shift slots — each with a start time, end time, and the number of employees needed per position and sub-position. This is the staffing demand the algorithm tries to fill.

Position Configuration

SettingDescription
PositionsThe list of positions at the company (e.g., Server, Bartender, Host). Each position can have sub-positions (e.g., Bar 1, Bar 2).
Position priorityA ranking that determines which positions get filled first during generation. Higher-priority positions are staffed before lower-priority ones.
Sub-position priorityWithin each position, sub-positions also have a priority order. Higher-priority sub-positions get staffed first.
Archived positionsPositions or sub-positions marked as archived are excluded from generation entirely.

Hour & Break Rules

SettingDescription
Default shift durationThe assumed length of a shift when no explicit end time is set (default: 4 hours). Used for open-ended shifts.
Minimum gap between shiftsThe minimum rest period required between two consecutive shifts on the same day (default: 30 minutes). If two shifts are closer than this gap, the employee cannot be assigned both.
Maximum hours per dayA company-wide cap on how many hours any single employee can work in one day. If not set, there is no daily limit.
Break rulesDefines unpaid break durations based on total shift hours (e.g., shifts over 7 hours include a 30-minute break, over 10 hours include a 60-minute break).
Exclude breaks from hoursWhen enabled, break time is subtracted from the employee's tracked weekly hours. This means longer shifts "cost" less against the employee's weekly budget.

Schedule Controls

SettingDescription
Closed daysDays the business is closed — no shifts are generated for these dates. Can be set per week or overridden at generation time.

Employee Settings & Preferences

These are per-employee settings. Some are managed by the administrator, others can be updated by employees themselves.

Profile & Status

SettingDescription
Active statusOnly active employees are considered for generation. Deactivated employees are excluded entirely.
Assigned positionsThe positions (and sub-positions) an employee is trained for and can work. An employee must have at least one assigned position to appear in generation. An employee can only be assigned shifts for positions they hold.

Weekly Availability

Each employee has a weekly availability profile that defines when they can work:

SettingDescription
Day availabilityFor each day of the week, the employee is either available or unavailable. If available, they can be marked as available all day or during a specific time window (e.g., 8:00 AM to 4:00 PM). The algorithm only assigns shifts that fit within the employee's declared availability window.
Maximum hours per weekThe total number of hours the employee can work in a given week. The algorithm tracks remaining hours after each assignment and stops scheduling the employee once their budget is exhausted.
Maximum days per weekThe maximum number of distinct days the employee prefers to work per week (0–7). Enforced across all phases — the algorithm will never schedule an employee on more days than this value. Defaults to 5 if not set. Note: this counts distinct calendar days, not shifts — an employee with max 1 day can still receive 2 shifts on that same day. If set to 0, the employee receives no shifts at all. This limit interacts with max hours per week — whichever limit is reached first will stop further assignments.
Approved availability overridesEmployees can submit availability change requests for future weeks via the mobile app. Once approved by a manager in the Requests module, the new availability is stored as a pending override with an effective date. During generation, the most recent approved override (up to end of target week) replaces the employee's base availability — including day-by-day windows, max hours per week, and max days per week. A daily cron job permanently applies overrides once their effective date arrives. See Availability Overrides section for full details.

Days Off

SettingDescription
Full day offThe employee is unavailable for the entire day. No shifts will be assigned.
Partial day offThe employee is unavailable during a specific time range (e.g., 9:00 AM to 1:00 PM). Shifts that overlap with the unavailable period are blocked, but shifts outside that window can still be assigned.

Priority & Seniority

SettingDescription
Employee priority (by position)Used in seniority mode. A numeric ranking at the position level, set in the Employees module. Determines the order in which employees are scheduled — higher-priority employees fill their entire schedule before anyone else. Employees at the bottom of the list may not receive any shifts if demand is already met.
Employee priority (by sub-position)Used in equal distribution mode. A numeric ranking at the sub-position level, set in the Employees module. Acts as a tiebreaker when two employees have the same number of shifts — the higher-priority employee gets the next shift.
Sub-position preferenceUsed in seniority mode only. Employees can set a preferred sub-position ordering per day (e.g., "prefer Bar 1 over Bar 2 on Mondays"). When filling shifts for a senior employee, the algorithm tries their preferred sub-positions first before falling back to default priority order.

Recurring Shift Templates

SettingDescription
Recurring patternsEmployees can have repeating weekly or multi-week templates that pre-assign them to specific positions, days, and periods (e.g., "every Monday morning at Bar 1"). These are placed first in Phase 1 before any other assignment.
Period or specific shiftA recurring template can target either a period (morning or evening — any shift in that period) or a specific shift slot (a named shift from the day structure).
On-hold recurring shiftsRecurring templates can be marked as on-hold (tentative). These are processed in a separate pass after all regular recurring shifts.
Template-only employeesIf an admin marks a template week as "Complete" in the Fixed Schedule UI, the employee is treated as template-only for that week. They are skipped during Phases 2, 3, and 4 — only their recurrent shifts from Phase 1 are assigned. This is a manual toggle, not automatically computed. If the recurrent shifts can't be placed (e.g., availability mismatch), the employee may end up with fewer shifts or none — there is no fallback to regular assignment.

Hard Limits (not configurable per employee)

These limits are enforced by the system and cannot be changed:

RuleDescription
Maximum 2 shifts per dayNo employee can be assigned more than 2 shifts on a single day, regardless of other settings.
6th day ruleNo employee can be scheduled on a 6th distinct day in the week through regular assignment (Phases 2, 3, 4). This is a hardcoded safety cap independent of the max days per week setting. Exception: the recurrent phase (Phase 1) does not enforce this rule — if an employee has recurring templates on 6 or 7 days and their max days per week allows it, all will be assigned.

Flow Summary

See the pipeline diagram at the top of The 4-Phase Process section for a visual overview of the full generation flow.


Key Characteristics

  • Greedy algorithm: assigns the best available option at each step rather than solving globally — fast but not mathematically optimal
  • No backtracking: once a shift is assigned it stays (except during the swap phase)
  • Near-instant: completes in milliseconds for typical team sizes
  • Deterministic: same inputs always produce the same schedule
  • Draft-first: the generated schedule is always a draft that the manager can review and adjust before publishing to employees
  • Additive: generation builds on top of existing shifts rather than starting from scratch, so manual edits and previous generations are preserved