Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
    • Pick-up and Delivery Routing
    • Task Scheduling
  • Platform
Try models
  • Task Scheduling
  • User guide
  • Freeze jobs until

Task Scheduling

    • Introduction
    • Getting started: Hello world
    • User guide
      • Terminology
      • Scheduling API concepts
      • Integration
      • Constraints
      • Using the API
        • Using the OpenAPI spec
        • API tooling
      • Demo datasets
      • Input datasets
        • Model configuration
        • Model input
      • Output datasets
        • Metadata
        • Model output
        • Input metrics
        • Key performance indicators (KPIs)
      • Job types and machine types
      • Resource-specific durations
      • Freeze jobs until
      • Metrics and optimization goals
      • Score analysis
      • Validation
    • Machine and employee resource constraints
      • Machine unavailability
      • Resource transitions
      • Employee resources
    • Job service constraints
      • Time windows
      • Time management
      • Job dependencies
      • Priority jobs
      • Tags and specific resources
    • Real-time planning
    • Changelog
    • Upgrading to the latest versions
    • Feature requests

Freeze jobs until

The freezeJobsUntil feature allows you to automatically pin all jobs on a resource that start before a specific time. This is useful for real-time planning scenarios where you want to lock in assignments that have already started or are about to start.

1. Basic usage

The freezeJobsUntil field on a machine or employee specifies a cutoff time. All jobs assigned to that machine or employee with a processing start before this time will be automatically pinned:

{
  "machines": [
    {
      "id": "Machine A",
      "start": "2024-12-01T00:00:00+00:00",
      "freezeJobsUntil": "2024-12-01T12:00:00+00:00",
      "jobs": [
        {
          "id": "Job 1",
          "start": "2024-12-01T08:00:00+00:00"
        },
        {
          "id": "Job 2",
          "start": "2024-12-01T14:00:00+00:00"
        }
      ]
    }
  ],
  "jobs": [
    {
      "id": "Job 1",
      "duration": "PT2H"
    },
    {
      "id": "Job 2",
      "duration": "PT3H"
    },
    {
      "id": "Job 3",
      "duration": "PT1H"
    }
  ]
}

In this example:

  • Job 1 starts at 08:00, which is before the freeze time of 12:00, so it will be pinned to Machine A.

  • Job 2 starts at 14:00, which is after the freeze time, so it can be rescheduled.

  • Job 3 is not yet assigned, so it can be assigned anywhere.

2. How freezeJobsUntil works

When you submit a schedule with freezeJobsUntil set:

  1. The system examines all jobs currently assigned to that machine or employee.

  2. For each job, it checks if the job’s processing start time is before the freezeJobsUntil time.

  3. If yes, the job is automatically pinned to that machine or employee at that position.

  4. The solver will not move, reschedule, or reassign these pinned jobs.

This is equivalent to manually setting pinned: true on each qualifying job, but more convenient when you want to freeze everything up to a certain time.

For more information on manual pinning, see Real-time planning.

3. Use cases

3.1. Rolling horizon planning

In continuous planning scenarios, you periodically re-plan the schedule but want to lock in the near-term decisions:

{
  "machines": [
    {
      "id": "Production line",
      "start": "2024-12-01T00:00:00+00:00",
      "freezeJobsUntil": "2024-12-01T08:00:00+00:00",
      "jobs": [
        { "id": "Job 1", "start": "2024-12-01T00:00:00+00:00" },
        { "id": "Job 2", "start": "2024-12-01T04:00:00+00:00" },
        { "id": "Job 3", "start": "2024-12-01T10:00:00+00:00" }
      ]
    }
  ]
}

At midnight, you re-plan with freezeJobsUntil set to 08:00. This locks Job 1 and Job 2 in place, while Job 3 and any new jobs can be rescheduled.

3.2. Jobs in progress

When jobs are already being processed, you cannot reassign them:

{
  "employees": [
    {
      "id": "Technician 1",
      "start": "2024-12-01T08:00:00+00:00",
      "freezeJobsUntil": "2024-12-01T12:00:00+00:00",
      "jobs": [
        {
          "id": "Ongoing service",
          "start": "2024-12-01T10:00:00+00:00"
        }
      ]
    }
  ],
  "jobs": [
    {
      "id": "Ongoing service",
      "duration": "PT4H"
    }
  ]
}

If it’s currently 11:00, the ongoing service call started at 10:00 (before the freeze time) and will be pinned. The technician cannot be reassigned from this job.

3.3. Commitment horizon

You may have communicated start times to customers or other stakeholders and cannot change them:

{
  "machines": [
    {
      "id": "Machine A",
      "start": "2024-12-01T00:00:00+00:00",
      "freezeJobsUntil": "2024-12-03T00:00:00+00:00",
      "jobs": [
        { "id": "Customer A order", "start": "2024-12-01T08:00:00+00:00" },
        { "id": "Customer B order", "start": "2024-12-02T08:00:00+00:00" },
        { "id": "Customer C order", "start": "2024-12-04T08:00:00+00:00" }
      ]
    }
  ]
}

Customer A and B have been notified of their start times (before Dec 3rd), so those are frozen. Customer C’s order (after Dec 3rd) can still be adjusted.

4. Combining with manual pinning

You can use both freezeJobsUntil and manual pinning on individual jobs:

{
  "machines": [
    {
      "id": "Machine A",
      "start": "2024-12-01T00:00:00+00:00",
      "freezeJobsUntil": "2024-12-01T12:00:00+00:00",
      "jobs": [
        { "id": "Job 1", "start": "2024-12-01T08:00:00+00:00" },
        { "id": "Job 2", "start": "2024-12-01T15:00:00+00:00" }
      ]
    }
  ],
  "jobs": [
    {
      "id": "Job 1",
      "duration": "PT2H"
    },
    {
      "id": "Job 2",
      "duration": "PT3H",
      "pinned": true
    }
  ]
}

In this example:

  • Job 1 is pinned because it starts before 12:00 (automatic via freezeJobsUntil)

  • Job 2 is pinned because it has pinned: true (manual), even though it starts after 12:00

5. Employees and machines

The freezeJobsUntil feature works with both machines and employees:

{
  "employees": [
    {
      "id": "Employee 1",
      "start": "2024-12-01T08:00:00+00:00",
      "freezeJobsUntil": "2024-12-01T10:00:00+00:00",
      "jobs": [
        {
          "id": "Morning task",
          "start": "2024-12-01T08:00:00+00:00"
        }
      ]
    }
  ],
  "machines": [
    {
      "id": "Machine A",
      "start": "2024-12-01T00:00:00+00:00",
      "freezeJobsUntil": "2024-12-01T06:00:00+00:00",
      "jobs": [
        {
          "id": "Overnight job",
          "start": "2024-12-01T00:00:00+00:00"
        }
      ]
    }
  ]
}

Each resource can have its own freezeJobsUntil time, allowing fine-grained control over which assignments are locked.

6. Important constraints

When using freezeJobsUntil, be aware of these requirements:

6.1. Job sequence integrity

You can only pin a job if all preceding jobs on the same resource are also pinned. The freezeJobsUntil mechanism respects this by only pinning jobs that start before the cutoff time.

{
  "machines": [
    {
      "id": "Machine A",
      "start": "2024-12-01T00:00:00+00:00",
      "freezeJobsUntil": "2024-12-01T10:00:00+00:00",
      "jobs": [
        {
          "id": "Job 1",
          "start": "2024-12-01T00:00:00+00:00"
        },
        {
          "id": "Job 2",
          "start": "2024-12-01T04:00:00+00:00"
        },
        {
          "id": "Job 3",
          "start": "2024-12-01T08:00:00+00:00"
        },
        {
          "id": "Job 4",
          "start": "2024-12-01T12:00:00+00:00"
        }
      ]
    }
  ]
}

In this example, jobs 1, 2, and 3 all start before 10:00 and will be pinned. Job 4 starts after 10:00 and can be rescheduled, along with any new jobs.

6.2. Timing and dependencies

Pinned jobs maintain their start and end times. If other jobs depend on pinned jobs, those timing relationships are preserved.

{
  "machines": [
    {
      "id": "machine A",
      "start": "2024-12-01T00:00:00+00:00",
      "freezeJobsUntil": "2024-12-01T12:00:00+00:00",
      "jobs": [
        { "id": "prep", "start": "2024-12-01T08:00:00+00:00" }
      ]
    }
  ],
  "jobs": [
    {
      "id": "prep",
      "duration": "PT2H"
    },
    {
      "id": "main work",
      "duration": "PT4H",
      "dependencies": [
        { "id": "prep" }
      ]
    }
  ]
}

The prep job is pinned to start at 08:00 and finish at 10:00. The main work job depends on prep, so it cannot start before 10:00, regardless of where it’s assigned.

For more information on dependencies, see Job dependencies.

7. Real-time planning workflow

A typical real-time planning workflow using freezeJobsUntil:

  1. Initial schedule is created and jobs begin processing

  2. Time passes, and some jobs start or complete

  3. New jobs arrive or requirements change

  4. Create a new planning request including:

    • Current job assignments with their start times

    • freezeJobsUntil set to the current time (or slightly in the future)

    • New jobs to be scheduled

    • Any updated requirements

  5. Submit for re-planning

  6. The solver respects all pinned jobs and optimizes the remaining assignments

{
  "machines": [
    {
      "id": "machine A",
      "start": "2024-12-01T00:00:00+00:00",
      "freezeJobsUntil": "2024-12-01T14:00:00+00:00",
      "jobs": [
        { "id": "completed job", "start": "2024-12-01T08:00:00+00:00" },
        { "id": "in progress", "start": "2024-12-01T12:00:00+00:00" },
        { "id": "upcoming", "start": "2024-12-01T16:00:00+00:00" }
      ]
    }
  ],
  "jobs": [
    { "id": "completed job", "duration": "PT2H" },
    { "id": "in progress", "duration": "PT3H" },
    { "id": "upcoming", "duration": "PT1H" },
    { "id": "new urgent job", "duration": "PT2H", "priority": 10 }
  ]
}

At 14:00, the completed job and in-progress job are frozen. The upcoming job and new urgent job can be rescheduled as needed.

8. Best practices

  1. Set freeze time appropriately: Typically set to the current time or a short time in the future (e.g., 1-2 hours ahead)

  2. Include completed jobs: You can include completed jobs in the job list for historical context, but they won’t affect optimization

  3. Update regularly: In continuous planning, update the freezeJobsUntil time with each re-planning cycle

  4. Balance stability and flexibility: Freezing too far ahead reduces flexibility; freezing too little may cause unwanted changes

  5. Test your workflow: Verify that the freeze mechanism works as expected in your re-planning workflow

  6. Document your policy: Clearly document when and how far ahead you freeze jobs

Next

  • See the full API spec or try the online API.

  • Learn about real-time planning.

  • Learn about job dependencies.

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