Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
    • Pick-up and Delivery Routing
  • Platform
Try models
  • Timefold Solver SNAPSHOT
  • Using Timefold Solver
  • Building a service (Preview)
  • Exposing metrics (optional)
  • Edit this Page

Timefold Solver SNAPSHOT

    • Introduction
    • PlanningAI concepts
    • Getting started
      • Overview
      • Hello World Quick Start Guide
      • Quarkus Quick Start Guide
      • Spring Boot Quick Start Guide
      • Vehicle Routing Quick Start Guide
    • Using Timefold Solver
      • Using Timefold Solver: Overview
      • Configuring Timefold Solver
      • Modeling planning problems
      • Running Timefold Solver
      • Benchmarking and tweaking
      • Building a service (Preview)
        • REST API
        • Service Model and Enricher
        • Constraint weights (optional)
        • Demo data (optional)
        • Exposing metrics (optional)
    • Constraints and score
      • Constraints and Score: Overview
      • Score calculation
      • Understanding the score
      • Adjusting constraints at runtime
      • Load balancing and fairness
      • Performance tips and tricks
    • Optimization algorithms
      • Optimization Algorithms: Overview
      • Construction heuristics
      • Local search
      • Exhaustive search
      • Neighborhoods: A new way to define custom moves
      • Move Selector reference
    • Responding to change
    • Integration
    • Design patterns
    • FAQ
    • New and noteworthy
    • Upgrading Timefold Solver
      • Upgrading Timefold Solver: Overview
      • Upgrade from Timefold Solver 1.x to 2.x
      • Upgrading from OptaPlanner
      • Backwards compatibility
      • Migration Guides
        • Variable Listeners to Custom Shadow Variables
        • Chained planning variable to planning list variable
    • Plus/Enterprise Editions
      • Installation
      • Performance improvements
      • Score analysis
      • Recommendation API
      • Nearby selection
      • Multithreaded solving
      • Partitioned search
      • Constraint profiling
      • Multistage moves
      • Throttling best solution events

Exposing metrics (optional)

Timefold Solver provides a mechanism to collect metrics about both the input submitted to the solver and the output it produces. These metrics are automatically exposed through the REST API alongside the optimization result, making it straightforward to build dashboards, monitoring screens, and insights views on top of them, without any additional endpoints or custom logic.

This page describes features which are only relevant when running Timefold Solver as a Service (Preview). The information on these pages may describe functionality which may be changed or even removed in a future release.

1. Input metrics

Input metrics provide more information about the data provided to the solver. The metrics should be contained in a class or record which implements the ModelInputMetrics interface.

The input metrics will be exposed through the REST API, for which an OpenAPI spec will be generated. It is therefore necessary to add OpenAPI Specification annotations to the fields.

Example for School Timetabling
public record TimetableInputMetrics(
    @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) @Schema(name = "lessons", title = "Lessons",
            format = DataFormat.Values.NUMBER, description = "The number of lessons submitted in the input dataset.",
            type = SchemaType.NUMBER, example = "10", readOnly = true) int lessons,
    @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) @Schema(name = "timeslots", title = "Timeslots",
            format = DataFormat.Values.NUMBER, description = "The number of timeslots submitted in the input dataset.",
            type = SchemaType.NUMBER, example = "30", readOnly = true) int timeslots
   ) implements ModelInputMetrics {}

Next, the SolverModel should implement the InputMetricsAware interface and construct the defined ModelInputMetrics object.

Example for School Timetabling
@PlanningSolution
public class Timetable implements SolverModel<HardSoftScore>, InputMetricsAware<TimetableInputMetrics> {

    @ProblemFactCollectionProperty
    @ValueRangeProvider
    private List<Timeslot> timeslots;

    @PlanningEntityCollectionProperty
    private List<Lesson> lessons;

    @PlanningScore
    private HardSoftScore score;

    @Override
    public HardSoftScore getScore() {
        return score;
    }

    @Override
    public TimetableInputMetrics getInputMetrics() {
        return new TimetableInputMetrics(lessons.size(), timeslots.size());
    }

    // other Getters/Setters/Constructors excluded
}

2. Output metrics

Output metrics provide more information about the result produced by the solver, such as solution quality indicators or key performance indicators (KPIs).

Output metrics are calculated after solving completes. They should be derived from the solved SolverModel, not from the input.

Like input metrics, they are exposed through the REST API under the kpis field of the response. It is therefore necessary to add OpenAPI Specification annotations to the fields.

Example for School Timetabling
public record TimetableOutputMetrics(
    @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) @Schema(name = "unassignedLessons", title = "Unassigned lessons",
            format = DataFormat.Values.NUMBER, description = "The number of lessons that could not be assigned a timeslot or room.",
            type = SchemaType.NUMBER, example = "0", readOnly = true) int unassignedLessons,
    @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) @Schema(name = "maxConsecutiveLessons", title = "Max consecutive lessons",
            format = DataFormat.Values.NUMBER, description = "The maximum number of consecutive lessons assigned to any single teacher.",
            type = SchemaType.NUMBER, example = "3", readOnly = true) int maxConsecutiveLessons
   ) implements ModelOutputMetrics {}

Next, the SolverModel should implement the OutputMetricsAware interface and construct the defined ModelOutputMetrics object from the solved state.

Example for School Timetabling
@PlanningSolution
public class Timetable implements SolverModel<HardSoftScore>, OutputMetricsAware<TimetableOutputMetrics> {

    @ProblemFactCollectionProperty
    @ValueRangeProvider
    private List<Timeslot> timeslots;

    @PlanningEntityCollectionProperty
    private List<Lesson> lessons;

    @PlanningScore
    private HardSoftScore score;

    @Override
    public HardSoftScore getScore() {
        return score;
    }

    @Override
    public TimetableOutputMetrics getOutputMetrics() {
        int unassigned = (int) lessons.stream()
                .filter(l -> l.getTimeslot() == null || l.getRoom() == null)
                .count();
        int maxConsecutive = computeMaxConsecutiveLessons(lessons);
        return new TimetableOutputMetrics(unassigned, maxConsecutive);
    }

    // other Getters/Setters/Constructors excluded
}

3. Combining input and output metrics

A SolverModel can implement both InputMetricsAware and OutputMetricsAware at the same time.

@PlanningSolution
public class Timetable implements SolverModel<HardSoftScore>,
        InputMetricsAware<TimetableInputMetrics>,
        OutputMetricsAware<TimetableOutputMetrics> {

    // fields, getInputMetrics(), getOutputMetrics() excluded

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