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 3
  • 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 3: Managing employee types

Introduction

In most organizations, there are different types of employees, who may have different rules that apply to them. For example, some employees may be full-time, while others are part-time. Some employees may be on a fixed-term contract, while others are permanent. Some employees may be unionized, while others are not. Employees from different departments may follow different rules.

A contract in Timefold is a defined set of working rules. It can apply to one or more employees at once. It is the best way to differentiate the groups of employees that follow different rules for shift assignment. For example:

  • A full-time employee may have a maximum of 38 hours of work per week, while a part-time employee may have a maximum of 23 hours of work per week.

  • A unionized employee may not be allowed to work more than three night shifts in a row, while a non-unionized employee may be allowed to work more night shifts.

  • A department A employee may not be allowed to work more than four shifts in any eight days, while a department B employee may be allowed to work five shifts in every seven days.

It is a good idea to pause here briefly and think of all the different employee subgroups that exist in your organization, and the different rules that apply to each of them. Gaining a deep understanding of your specific scheduling problem is very valuable before trying to convert it into Timefold constraints.

Employee contracts

Contracts are where rules are defined, which must be followed by employees. At minimum, each contract object must include an id.

  • id can be any string of your choice. The id is the globally unique identifier for each individual contract, which can be assigned to one or more employees.

A contract can hold any number of rules, all of which will apply to every employee who is assigned that contract. Some of these rules will be covered in later lessons, and all are documented in the technical documentation. For now, we will just work with placeholder contracts that only have an id, as follows:

{
  "contracts": [
    {
      "id": "fullTimeContract"
    },
    {
      "id": "partTimeContract"
    },
    {
      "id": "departmentAContract"
    }
  ]
}

Let’s say that Beth and Ann both work in department A, and Beth works full time while Ann works part time. In this scenario, Beth and Ann will both follow the department A contract. Additionally, Beth will follow the full time contract, while Ann will follow the part time contract. We can assign them their appropriate contracts like this:

{
  "employees": [
    {
      "id": "Beth",
      "contracts": [
        "fullTimeContract",
        "departmentAContract"
      ]
    },
    {
      "id": "Ann",
      "contracts": [
        "partTimeContract",
        "departmentAContract"
      ]
    }
  ]
}
These contracts currently don’t have any rules associated with them, but they are valid contracts. As they are currently, they would not apply any constraints to the employees that they are assigned to during solving.

Organizing contracts in a dataset

The above example shows us how multiple employees can have different contracts, and can also share the same contract. Some guidelines that should be followed for organizing contracts in a dataset are:

  • Minimize the number of large contracts in the dataset. The fewer contracts in memory, the faster the contract lookup will be, and the faster the dataset will solve.

  • Reduce the number of duplicate contracts. If two contracts have the same rules, only one contract should be created, and both employees should share that contract.

  • Try to re-use contracts where possible. If two employees have the same rules at the same time, they should share the same contract.

  • If two employees do not work the same rules, then split the contracts to minimize rule duplication in the dataset.

For example, let’s assume two employees have the same rules for hours worked, time between shifts, and travel to shifts, but they work different shift patterns. In this case, defining two contracts which both have all the rules for each employee would lead to duplication of the rules that they have in common. Instead, it would be better to define one contract which holds all the rules that they share to be assigned to both employees. Then, also define two more short contracts which hold the pattern rules that differ between them to be assigned individually.

Common errors to watch out for

When creating a dataset and assigning multiple contracts to one employee, it is important to be sure that you know which employees should be assigned which contracts. One common error is to assign clashing contracts to an employee. For example, let’s assume that a third employee, Carl, works full time. He gets assigned both the full time contract and the part time contract at the same time by mistake:

{
  "employees": [
    {
      "id": "Carl",
      "contracts": [
        "fullTimeContract",
        "partTimeContract"
      ]
    }
  ]
}

The Timefold model will always follow all the rules at the same time, even if these rules directly clash with each other. Therefore, whichever of the contracts has the most restrictive rules will be the ones that are followed. For example, if the full time contract limits Carl to 38 hours of work per week, and the part time contract limits him to 23 hours of work per week, then the Timefold model will limit Carl to 23 hours per week. This is well within the higher 38 hour limit, and therefore satisfies both contracts. In this way, the Timefold model ensures that none of the rules are broken. But if Carl is supposed to work full time, then he will not be assigned as many hours of work as he is entitled to. If Carl worked part-time and was assigned both the above contracts, then the error would likely be less noticeable, since he would be following the lower limits of the part-time contract anyway.

It is also common to accidentally not assign a contract to an employee which should have been assigned. This will lead to them working shift patterns and configurations which are not viable for their working agreements.

It is a good idea to apply some validation after the dataset has been created to check which employees have been assigned which contracts. The Timefold model will not flag errors like the above, because we allow any employee to be assigned any (or no) contract, for full flexibility.

Another common error is to assign a contract that doesn’t exist in the dataset to an employee. This could be due to a legitimate contract not having been created when it should have been, cross-dataset confusion when creating multiple datasets at once with different contracts in each dataset, or simply due to a typo. In such a case, the dataset will be rejected by the Timefold API, and a validation error will be returned indicating that the contract does not exist. The error message will look something like this:

{
  "id": "7c50f503-6dfd-4298-a2f3-97f565ced9f5",
  "originId": "7c50f503-6dfd-4298-a2f3-97f565ced9f5",
  "name": "Dataset name",
  "submitDateTime": "2026-09-21T14:46:31.978943175+01:00",
  "solverStatus": "DATASET_INVALID",
  "tags": [],
  "validationResult": {
    "summary": "ERRORS",
    "errors": [
      "Employee (Carl) references a contract (wrongNameContract) that does not exist in the schedule."
    ]
  }
}

Conclusion

In this lesson, we covered:

  • The basics of contracts and how to think about splitting employees into different groups based on the rules that apply to them.

  • How to assign contracts to employees in the input dataset.

  • How to organize contracts in a dataset to minimize duplication and maximize re-use.

  • What common errors to look out for in contract assignment.

Next

  • Proceed to Lesson 4 to learn about a common rule to configure in contracts: limits to working time.

  • Discover more in-depth technical details about contracts in the Employee Contracts documentation of the user guide.

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

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