Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
    • Pick-up and Delivery Routing
    • Task Scheduling
  • Platform
Start Free Trial
  • Employee Shift Scheduling
  • Lessons overview
  • Lesson 2
  • latest
    • latest
    • 1.35.x
    • 1.34.x

Employee Shift Scheduling

    • Introduction
    • Getting started: Hello world
    • Lessons overview
      • Lesson 1
      • Lesson 2
      • Lesson 3
      • Lesson 4
      • Interlude 1: Basic demo data
    • User guide
      • Terminology
      • Use case guide
      • Scheduling API concepts
      • Integration
      • Constraints
      • Using the API
        • Using the OpenAPI spec
        • API tooling
      • Demo datasets
      • Input datasets
        • Model configuration
        • Model input
        • Planning window
      • Planning window
      • Time zones and Daylight Saving Time (DST)
      • Tags and tag types
      • Input validation
      • Output datasets
        • Metadata
        • Model output
        • Input metrics
        • Key performance indicators (KPIs)
      • Metrics and optimization goals
      • Score analysis
      • Visualization
      • Efficiency X-Ray
      • Assignability analysis
    • Employee resource constraints
      • Employee availability and preferences
        • Employee availability
        • Employee preferences
      • Employee contracts
      • Employee priority
      • Pairing employees
      • Employee groups
      • Shift travel and locations
      • Shift Breaks
      • Employee activation
      • Work limits
        • Minutes worked per period
        • Minutes worked in a rolling window
        • Minutes logged per period
        • Days worked per period
        • Days worked in a rolling window
        • Consecutive days worked
        • Shifts worked per period
        • Shifts worked in a rolling window
        • Weekend minutes worked per period
        • Weekends worked per period
        • Weekends worked in a rolling window
        • Consecutive weekends worked
        • Consecutive shifts worked
      • Time off
        • Days off per period
        • Consecutive days off per period
        • Consecutive days off in a rolling window
        • Consecutive minutes off in a rolling window
        • Shifts to avoid close to day off requests
        • Consecutive weekends off per period
      • Shift rotations and patterns
        • Shift rotations
        • Single day shift sequence patterns
        • Minimize gaps between shifts
        • Multi-day shift sequence patterns
        • Daily shift pairings
        • Overlapping shifts
        • Shift start times differences
        • Minutes between shifts
      • Shift type diversity
        • Shift tag types
        • Shift types worked per period
        • Unique tags per period
      • Fairness
        • Balance time worked
        • Balance shift count
    • Shift service constraints
      • Alternative shifts
      • Cost management
        • Cost groups
        • Employee rates
      • Demand-based scheduling
      • Priority and optional shifts
      • Skills and risk factors
      • Shift assignments
        • Shift selection
        • Employee selection
    • Manual intervention
    • Recommendations
    • Real-time planning
    • Scenarios
      • Configuring labor law compliance
      • Configuring employee well-being
      • Self-rostering and optimization
    • Changelog
    • Upgrade to the latest version
    • Feature requests

Lesson 2: Limiting employees to certain shifts

Introduction

One of the most common restrictions on employee schedules is that certain employees can or cannot work certain shifts. This may be due to any number of reasons, such as:

  • Missing required qualifications, such as "Forklift certified" or "Supervisor".

  • Having an incorrect level of qualifications, such as "Plumber level 1" instead of "Plumber level 3".

  • Not being old enough to work a shift, for example if employees aged 16 cannot handle adult beverages.

  • Not being allowed to work in a certain department or at a certain location.

  • Not being allowed to work a certain shift due to union rules, such as not being allowed to work night shifts.

  • Personal accommodations, such as not being allowed to work certain shifts due to the potential for allergen exposure.

This lesson covers how to handle any scenario in which some employees are included or excluded from working certain shifts in a simple yes/no manner.

Skills

Traditionally, a "skill" is the term used to describe some technical knowledge or proficiency that an employee has. In Timefold, this concept has evolved to include any type of inclusionary or exclusionary criteria that is used to determine if an employee is allowed to work a shift. This includes the traditional concept of skills. It also includes any other criteria which is used to match employees to shifts through a simple binary yes/no decision, such as age, department, location, union rules, and personal accommodations.

Any inclusionary criteria that is used to determine whether an employee is allowed to work a shift can be thought of as a "skill" in Timefold. A skill can be any string, including coded or anonymized strings which do not represent real words in any language.

When creating a schedule, think of all the requirements on your shifts which qualify certain employees to work those shifts. It is important to capture as much of this information as possible, so that the Timefold model can assign shifts to the most appropriate employees. The more information you provide, the better the Timefold model can approach the scheduling problem.

It is a good idea to pause here briefly and think of all the particular requirements which your organization has for matching your shifts to employees. Gaining a deep understanding of your specific scheduling problem is very valuable before trying to convert it into Timefold constraints.

Let’s re-visit the example schedule from the Getting Started guide. Here is the JSON input dataset for that example:

{
  "config": {
    "run": {
      "name": "Hello world example"
    }
  },
  "modelInput": {
    "employees": [
      {
        "id": "Beth"
      }
    ],
    "shifts": [
      {
        "id": "Mon",
        "start": "2027-02-01T00:00:00Z",
        "end": "2027-02-01T08:00:00Z"
      }
    ]
  }
}

Consider the shift in this example. Let’s pretend that this is a night shift in the bakery department of a supermarket. We can represent these requirements in Timefold by adding a list of requiredSkills to the shift:

{
  "shifts": [
    {
      "id": "Mon Night Bakery shift",
      "start": "2027-02-01T00:00:00Z",
      "end": "2027-02-01T08:00:00Z",
      "requiredSkills": [
        "Night",
        "Bakery"
      ]
    }
  ]
}
By default, an employee must have all the required skills in order to be assigned to that shift. requiredSkills are treated as hard constraints.

If Beth can work night shifts and is allowed to work in the bakery, then she can be assigned to this shift. We represent this in Timefold by adding a list of skills to Beth, each of which must have an id to be matched to the requiredSkills of the shift:

{
  "id": "Beth",
  "skills": [
    {
      "id": "Night"
    },
    {
      "id": "Bakery"
    }
  ]
}
By default, skills are active for the entire schedule.

Let’s say that Ann can work in the bakery, but she cannot work night shifts because she has not received the correct training. In this case, she does not have the skill Night required to work this shift, and would never be assigned:

{
  "id": "Ann",
  "skills": [
    {
      "id": "Bakery"
    }
  ]
}
Skill requirements are case-sensitive. Make sure that the skill names match exactly between the employee and the shift.

Skills are generally used to include those employees which can work the shift. If there is an exclusionary factor, for example one of the employees has a shellfish allergy and cannot work shifts that would expose them to their allergen, this is generally represented as a risk factor instead.

Risk factors

Risk factors are equivalent to skills, but work in the opposite manner. They exclude employees who have those risk factors from working those shifts.

Similar to skills, a risk factor can be any string, including coded or anonymized strings which do not represent real words in any language.

To exclude an employee based on risk factors, for instance, a shellfish allergy, add the list of riskFactors to the shift:

{
  "shifts": [
    {
      "id": "Mon Night Bakery Shellfish shift",
      "start": "2027-02-01T00:00:00Z",
      "end": "2027-02-01T08:00:00Z",
      "requiredSkills": [
        "Night",
        "Bakery"
      ],
      "riskFactors": [
        "Shellfish allergy"
      ]
    }
  ]
}

In this example, Beth has the skills required for the shift and does not have the risk factor. Suppose Ann has since completed her night training, so she now has the Night skill as well. However, she has a shellfish allergy, and therefore she has the risk factor which disqualifies her from being assigned to this shift. The employees would look like this:

{
  "employees": [
    {
      "id": "Beth",
      "skills": [
        {
          "id": "Night"
        },
        {
          "id": "Bakery"
        }
      ]
    },
    {
      "id": "Ann",
      "skills": [
        {
          "id": "Night"
        },
        {
          "id": "Bakery"
        }
      ],
      "prohibitedRiskFactors": [
        "Shellfish allergy"
      ]
    }
  ]
}
In general, we recommend representing anything which qualifies an employee for a shift as a skill, and anything which disqualifies an employee from a shift as a risk factor. This is a good practice to follow, but under the hood, they are equivalent.

Practical example

Skills and risk factors: Beth is assigned the shift and Ann is excluded by the shellfish allergy risk factor
  • Input

  • Output

Try this example in Timefold Platform by saving this JSON into a file called sample.json and making the following API call:
curl -X POST -H "Content-type: application/json" -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/employee-scheduling/v1/schedules [email protected]
{
  "config": {
    "run": {
      "name": "Lesson 2: including and excluding employees"
    }
  },
  "modelInput": {
    "employees": [
      {
        "id": "Beth",
        "skills": [
          {
            "id": "Night"
          },
          {
            "id": "Bakery"
          }
        ]
      },
      {
        "id": "Ann",
        "skills": [
          {
            "id": "Night"
          },
          {
            "id": "Bakery"
          }
        ],
        "prohibitedRiskFactors": [
          "Shellfish allergy"
        ]
      }
    ],
    "shifts": [
      {
        "id": "Mon Night Bakery Shellfish shift",
        "start": "2027-02-01T00:00:00Z",
        "end": "2027-02-01T08:00:00Z",
        "requiredSkills": [
          "Night",
          "Bakery"
        ],
        "riskFactors": [
          "Shellfish allergy"
        ]
      }
    ]
  }
}
To request the solution, locate the ID from the response to the post operation and append it to the following API call:
curl -X GET -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/employee-scheduling/v1/schedules/<ID>
{
  "metadata": {
    "id": "ID",
    "name": "Lesson 2: including and excluding employees",
    "submitDateTime": "2025-02-19T07:59:36.850272829Z",
    "startDateTime": "2025-02-19T07:59:42.88054275Z",
    "activeDateTime": "2025-02-19T07:59:42.93678946Z",
    "completeDateTime": "2025-02-19T08:04:43.16445426Z",
    "shutdownDateTime": "2025-02-19T08:04:43.307088825Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/0soft",
    "tags": [
      "system.profile:default"
    ],
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "shifts": [
      {
        "id": "Mon Night Bakery Shellfish shift",
        "employee": "Beth"
      }
    ]
  },
  "kpis": {
    "assignedShifts": 1,
    "unassignedShifts": 0,
    "workingTimeFairnessPercentage": null,
    "disruptionPercentage": 0.0,
    "averageDurationOfEmployeesPreferencesMet": null,
    "minimumDurationOfPreferencesMetAcrossEmployees": null,
    "averageDurationOfEmployeesUnpreferencesViolated": null,
    "maximumDurationOfUnpreferencesViolatedAcrossEmployees": null
  }
}

modelOutput contains the schedule with Beth assigned to the shift.

Conclusion

In this lesson, we have learned about:

  • Inclusionary and exclusionary criteria for matching employees to shifts, which are represented as skills and risk factors in Timefold.

  • Treating any criteria which lead to a binary yes/no decision as a skill or risk factor, rather than thinking of this as being limited to skills in the traditional sense of the word.

  • The equivalency between skills and risk factors, and where it is recommended to use one over the other.

Next

  • Proceed to Lesson 3 to learn about how to work with different contracts for different employees.

  • Alternatively, go back to the Lessons overview to choose a different lesson to continue with.

This lesson introduced the basics of how to think about Timefold skills as inclusionary criteria. However, skills have more advanced features, such as:

  • Being limited to certain dates, rather than being active for the entire schedule.

  • Shifts requiring one of a set of skills, rather than all of them.

  • Shifts requiring complex combinations of skills, such as "Skill A" and one of "Skill B" or "Skill C".

  • Shifts preferring employees with certain skills (soft constraint), rather than only requiring them (hard constraint).

Explore these features in the Skills technical documentation of the user guide.

  • © 2026 Timefold BV
  • Timefold.ai
  • Documentation
  • Changelog
  • Send feedback
  • Privacy
  • Legal
    • Light mode
    • Dark mode
    • System default