new
improved
fixed
Timefold Platform
Employee Shift Scheduling
Field Service Routing
Pickup & Delivery Routing
Comparison CSV export, imperial units, employee groups and demand coverage KPIs (ESS), and more
Today, we're announcing version v1.14 of the Timefold Platform and updates to the Timefold models.
This new version of the Timefold Platform comes with these platform improvements:
- Take comparison results into your own tools with CSV export: You can now export a comparison to CSV from itsSharemenu. The file contains the visible comparison rows, with a value, difference, and difference-as-percentage column per dataset. The KPI aggregation popover of a comparison now also shows the sum, next to the minimum, maximum, average, and median. The saved comparisons list now also shows which model each comparison was built on. See comparison and saved comparisons for more details.
- See distances in miles and feet: You can now choose how the platform shows distances. Open the profile menu by clicking the cogwheel in the top-right corner of the header, then selectUnitsand choose one of these options: the system default, metric, or imperial. With imperial units, the platform shows distances in miles and feet. By default, the platform follows your browser's locale, and it remembers your choice in the browser, just like the theme setting.
- Pick or upload datasets faster when adding a new plan: We've redesigned the first step of the New plan dialog. You now pick a dataset from a dropdown that shows each dataset's short description, and the selected demo dataset's description and constraints appear below it. To use your own data, drag and drop your file, or browse for it, directly inside theCustomoption, which takes two steps instead of three. The dialog also has a newCancelbutton. TheImportprofile dialog uses the same drop zone, so you can drop an exported profile in as well as browse for it. See New plan and Export and import profiles for more details.
- More reliable server-sent events: The events stream (GET …/{id}/events) now closes after it sends the event for the dataset's final status (for datasets submitted without solving, that'sDATASET_COMPUTED). We also fixed an issue where events for a dataset could stop arriving when another dataset finished. A heartbeat comment every 30 seconds now keeps proxies from closing idle connections. If your client reconnects automatically, treat a close after the final status as the expected end of the stream. See events stream and Connection lifecycle for more details.
- Filter notification logs by trigger: You can now filter the notification logs by trigger, and open a trigger's edit dialog directly from a log's details. The log details now also show the execution duration. See notification logs for more details.
- Delete experiments and compare model versions on identical settings: You can now delete an experiment (preview) from the Experiments list, which also deletes the datasets its scenarios created. You can now leave out the configuration profile of an experiment scenario. The scenario then uses the settings it was originally solved with, which makes it easier to compare model versions on identical settings. See experiment for more details.
- Find datasets by ID and filter by profile name: Paste a full dataset ID into the search bar on the Plans overview to find that dataset directly. The configuration profile filter now offers your existing profile names in a dropdown. See Searching and filtering datasets for more details.
- See API versions in the model version picker: The model version picker now labels each version with its API version, such as v1 or v2, next to the build version. It also warns you when a model approaches the limit of ten parallel versions. See Semantic versioning for more details.
- A more compact model catalog: The model catalog is now a compact tile grid, with each model's maturity badge on its tile. See model catalog for more details.
- One consistent layout for lists and tables: Every list and data table in the platform now uses the same layout, with a toolbar for search and filters, striped rows, and a footer with pagination.
- Screen readers announce toasts: Screen readers now announce toasts, and each toast's dismiss button has an accessible name.
- Keyboard access to selected notification channels: When you select channels for a notification trigger, each selected channel's remove button is now reachable with the keyboard.
- Expandable sections report their state to assistive technology: Expandable sections, such as the advanced termination settings and validation issue groups, now tell assistive technology whether they're expanded.
- Expired items consistently highlighted: The platform now consistently highlights expired API keys, members, invites, and personal access tokens in red.
Next to that, this new version of the Timefold Platform comes with updates to these Timefold Models:
- Balance rules count only the shifts that match their shift tags: If you use more than one balance rule, each rule now balances only the shifts that match its shift tags, and counts each shift once. This lets the solver find schedules that are more balanced for each rule. We have fixed a bug where a shift was counted in every balance rule of its employee, also in rules whose shift tags do not match the shift. A shift that matched more than one rule was also counted once for each matching rule. The soft score of the balance shift count and balance time worked constraints changes for datasets with more than one balance rule. See Balance shift count and Balance time worked for more details.
- Tutorials to discover modeling concepts step by step: We have created a series of lessons designed to help you understand the concepts behind Timefold's Employee Shift Scheduling model, and how to use them to create a schedule that meets your business needs. They are aimed at new users of Timefold, but may also be useful for experienced users who want to deepen their understanding of modeling concepts. They are intended to complement the extensive technical documentation that already exists. Lessons can be viewed by navigating to the Lessons overview. More lessons will follow. See Lessons overview for more details.
- Choose which kinds of absence count toward absence-aware rules (preview): You can now limit absence awareness to specific kinds of absence, for example only sick leave, by tagging availability and unavailability time spans. Important: this is a breaking change to the previewabsenceModefield.absenceModewas a plain string ("ABSENCE_AWARE"or"ABSENCE_UNAWARE") and is now an object, for example"absenceMode": { "type": "ABSENCE_AWARE" }. Requests that still send the string value must be updated. OmittingabsenceModestill defaults toABSENCE_UNAWARE.absenceModenow also accepts anincludeDateTimeSpanTagsfield. WhenincludeDateTimeSpanTagsis non-empty, onlyunavailableTimeSpans/availableTimeSpansthat share at least one tag withincludeDateTimeSpanTagscount toward absence awareness. Spans without a matching tag are treated as if the employee were fully available during them. This lets you scope absence awareness to a specific kind of absence, for example only bridging gaps or scaling limits forsickleave, while avacation-tagged absence still breaks a consecutive-days streak or counts fully against a rolling-window limit. WhenincludeDateTimeSpanTagsis empty or omitted, every span counts, matching the previous behavior. Time spans also get a newtagsfield, matched againstabsenceMode.includeDateTimeSpanTags, that describes what a span represents, for example, the reason for an absence.includeDateTimeSpanTagsrequiresabsenceMode.typeto beABSENCE_AWARE. Absence-aware rules are a preview feature and subject to change. See Upgrade from 1.35.0 to 1.36.0, Consecutive days worked, Minutes between shifts, Minutes worked in a rolling window, Consecutive days off in a rolling window, Consecutive minutes off in a rolling window, and the Employee Shift Scheduling changelog for more details.
- See how well your hourly demand is staffed with new demand coverage KPIs: Schedules driven by hourly demand rules now report how well the demand curve was actually staffed, using three new demand coverage KPIs. All three are measured in person-time, soPT2Hmeans one employee for two hours, or two employees for one hour:hourlyDemandCoveragePercentage, the share of the required staffing that was met;uncoveredHourlyDemandPersonDuration, how much staffing is missing; andexcessHourlyDemandPersonDuration, how much staffing exceeds the maximum demand. Coverage is measured against each demand interval'sminDemand, and excess against itsmaxDemand. A KPI that cannot be measured is left out of thekpisobject rather than reported as zero, so a value of0always means "measured, and nothing is missing". All three are omitted when the dataset defines no hourly demand rules, and the two coverage figures are omitted when no demand interval defines aminDemand. These are distinct fromtotalDemandPersonSlots,coveredDemandPersonSlots, anduncoveredDemandPersonSlots, which describe how well automatically generated shifts blanket the demand curve, before any employee is assigned. See hourly demand rules, demand coverage KPIs, generated shifts, and the Employee Shift Scheduling changelog for more details.
- Limit the unique shift tags worked per period across the whole schedule (preview): GlobalminimumMaximumShiftsPerPeriodrules now support theuniqueTagsLimitfield, which caps how many distinct tags of the given tag types may be worked across all shifts in a period. Until nowuniqueTagsLimitwas only available on a contract'speriodRules, where the cap applies per employee, so there was no way to keep a whole operation on a single kind of task for a period. This is for operations that switch every shift over to one variant at a time, rather than limiting the variety any one employee sees. Any number of shifts can be staffed in the period, as long as they all carry the same tag. All the tag types listed inincludeTagTypesshare one budget, so listing two tag types with atagsMaxof 1 permits one distinct tag in total, not one distinct tag of each type. WhensatisfiabilityisREQUIRED, theUnique tags per period not in required rangehard constraint leaves shifts unassigned rather than exceedtagsMax. When it isPREFERRED, theUnique tags per period not in preferred rangesoft constraint penalizes each distinct tag abovetagsMaxinstead, and all shifts can still be assigned.uniqueTagsLimiton global rules is a preview feature and subject to change. See Limit unique shift tags worked per period and the Employee Shift Scheduling changelog for more details.
- Better schedules when limiting unique shift tags per period across the schedule: The model now uses a new custom move to better satisfy globalminimumMaximumShiftsPerPeriodrules that define auniqueTagsLimit. Previously, the model reached the allowed set of tags one shift at a time, so a period that had settled on the wrong tag could only be corrected by unassigning every shift carrying it first, which has a very low likelihood of happening. A new move now switches a whole period over to a different tag in one step, reassigning all the affected shifts together. The move is used automatically when any global rule also defines auniqueTagsLimit. See uniqueTagsLimit for more details.
- Employee groups on shifts (preview):employeeGroupsis a new top-level API that replaces grouping employees throughcommonTagType,groupByEmployeeTagandgroupShiftsPerDayLimiton employee pairings. Those fields have been removed from employee pairings. We have added a top-levelemployeeGroupscollection for cases where a set of employees must be considered together as a group rather than individually or as a pair. Each group declares explicit membership, split intorequiredEmployeesandpreferredEmployees: preferred members require at least one required member to be present, while required members can work alone but prefer other members of the group to also be present. Employee groups also supportcommonTagType, so that all working members of a group must share a concurrent shift with the same tag of that type, andgroupShiftsPerDayMax, capping how many different shift hours the group's members may work on the same day.employeeGroupsis a preview feature and subject to change. See Migrating from 1.35.0 to 1.36.0, Employee groups, and the Employee Shift Scheduling changelog for more details.
- Shifts ending at midnight no longer count toward the next day in global period rules: Global period rules now count a shift ending exactly at midnight only toward the periods it covers, so your period counts match the days your employees actually work. Previously, global period rules withperiodShiftOverlapKindset toSTART_AND_ENDalso counted that shift toward the following day's period. For example, a shift from 16:00 to 00:00 counted toward both the period containing its start and the period starting at 00:00. Global period rules now treat a shift's end time as exclusive, consistent with employee period rules, costs rules, and rolling window rules. This applies to global period rules both with and without a specified zone offset. See Global Period Rule and time zones for more details.
- More reliable server-sent events: This model's events stream also gets the improvements described under "More reliable server-sent events" in the Platform section above.
- Visit dependencies can now be enforced to be scheduled together: Previously, even when a visit dependency'scoordinationwas set toSAME_SHIFTorSAME_VEHICLE, the preceding visit could still be scheduled on its own while its dependent visit remained unassigned. The FSR model now allows requiring that the preceding and following visits of a dependency are scheduled together, or not at all, by specifying"coordination": "SAME_SHIFT_ENFORCE". When the preceding visit is scheduled, the following visit must be scheduled too, in the same vehicle shift. See Visit dependency coordination for more details.

- Understand how invalid coverage area geometries are repaired: When a vehicle's coverage area has invalid geometry, the model repairs it automatically. The documentation now explains how this repair works, including which library performs it. See Repairing invalid coverage area geometries for more details.
- Configurable proximity radius for grouping co-located visits: ThePrefer grouping co-located visitsconstraint previously only considered two itinerary items co-located if they shared the exact same location. A newpreferGroupingColocatedVisitsRadiusMetersoverride now lets you configure a proximity radius (in meters) instead, so that nearby-but-not-identical locations (for example, different geocoded units within the same building) are also considered co-located. The default is0, which preserves the original exact-location behavior, and the radius is capped at a maximum of200meters. It can be set globally, and overridden per vehicle shift or linked shift via their ownpreferGroupingColocatedVisitsRadiusMeters. See Prefer grouping co-located visits for more details.
- More reliable server-sent events: This model's events stream also gets the improvements described under "More reliable server-sent events" in the Platform section above.
- Require tags justification now names the missing tags: TheRequireTagsJustificationrecord has a new field:missingTagNames. This field lists the names of the tags a visit needs but the assigned vehicle shift does not have. Previously, the justification only showed the count of missing tags, not their names. See upgrade to the latest version page for more details.
- More reliable server-sent events: This model's events stream also gets the improvements described under "More reliable server-sent events" in the Platform section above.
- End location visualization: The end location of a shift was not being properly visualized in the visualization. This is now fixed with a hollow ring in the same color as the rest of the driver's route at the end location. The start location remains a solid circle in the same color as the rest of the driver's route. See visualization for more details.
Please let us know if you have feedback.