Skip to content
All worked examples

Public transport

GOIllustrative · 7 min read

Hard constraints wanted a solver, and the platform wanted deleting

A bus operator asked for machine learning to improve driver rostering. The algorithm question had a settled answer, because hard legal limits want a constraint solver. The finding worth the engagement was the platform the previous team had left behind, costing more each month than the problem was worth.

Two decisions kept deliberately apart. One settled by the literature, one nobody had asked about.

Problem

Rosters were built by hand in each depot, taking days and producing uneven work. Overtime was high and drivers complained about fairness. The incoming operations director asked for an AI rostering system.

Context

Several depots, a unionised workforce with a local agreement on rest and rotation, and a service contract with punctuality penalties.

Current architecture

A scheduling package of record, a set of microservices built by a previous team to ‘modernise’ around it, a managed Kubernetes cluster, two databases, and a message bus carrying traffic between four services that are always deployed together.

Constraints

  • Legal: driver hours are governed by hard limits, not preferences.
  • Industrial: the local agreement adds constraints beyond the law, and cannot be traded away by software.
  • Operational: a roster must be publishable weeks ahead and stable once published.
  • Skills: one platform engineer supports everything, and is the single point of failure for the cluster.

Evidence

Each statement placed on the ladder before it was used.

  • fact

    Regulation (EC) No 561/2006 applies to vehicles constructed or permanently adapted to carry more than nine persons including the driver, and sets daily driving of 9 hours (extendable to 10 hours twice a week), a 56-hour weekly limit, and a regular weekly rest of at least 45 hours in any two consecutive weeks. Article 3(a) then excludes regular passenger services whose route does not exceed 50 km, which covers much of this operator’s network and leaves those drivers under the applicable domestic rules instead.

    Source: Regulation (EC) No 561/2006; IRU guide to EU rules on drivers’ hours

  • fact

    Four of the six services are deployed together every time, share one database and have never been scaled independently. Established from deployment history and the cluster manifests.

    No external source: stated for the example

  • constraint

    A roster that breaches a hard limit is not a lower-scoring roster. It is an unlawful one.

    No external source: stated for the example

  • assumption

    Overtime is driven by poor rostering, not by absence. Believed in the depots; absence data suggested both matter.

    No external source: stated for the example

  • tradeoff

    Fairness and cost pull against each other, and the trade has to be decided by people, not inferred from history.

    No external source: stated for the example

Questions that changed the answer

  1. 01Which constraints are legal, which are contractual, and which are habit?
  2. 02Which regime applies to each service, 561/2006 or the domestic rules covering regular routes under 50 km? That question splits the network in two, and it was asked first.
  3. 03Is the objective minimum cost, maximum fairness, or stability once published? These give different rosters.
  4. 04What does the current platform cost to run and to keep secure, against what it is used for?
  5. 05If a model produced an unlawful roster, how would anyone notice before publication?

Options

Including the one nobody wanted to discuss.

  • Machine learning over historical rosters

    Learn from past rosters to propose new ones.

    What it costs: Learns historical practice including its unfairness, and cannot guarantee a hard constraint, the one property this problem requires.

  • Constraint solver with explicit rules

    chosen

    Encode legal and agreement constraints, choose an objective, and let a solver produce rosters that are correct by construction.

    What it costs: Requires the operator to state the objective out loud and agree it with the union; the hardest part of this is not technical.

  • Buy a rostering product

    Adopt a specialist package.

    What it costs: Strong fit for the legal rules, weaker for the local agreement; kept as a serious alternative and priced.

  • Leave the inherited platform as it is

    Build rostering on top of the existing cluster, message bus and six services.

    What it costs: Keeps a monthly bill larger than the problem is worth, and makes the new code inherit the estate’s deployment and on-call story.

  • Collapse the co-deployed services and retire the cluster

    chosen

    Merge the four services that always ship together into one, drop the message bus, retire the managed cluster.

    What it costs: Weeks of work with no user-visible feature at the end of it, and it has to be sequenced before the rostering build to be worth doing.

Economics

Four horizons, not one estimate.

Build
A solver model plus a constraint library. Small, and mostly analysis rather than code.
Run
The decisive finding. The existing cluster cost more each month than the rostering problem was estimated to be worth, for four services that deploy as one.
Change
Agreement changes are a constraint edit in the solver; in the current estate the same change touches several services and a bus.
Exit
Low for the solver. The constraints are written down and portable. High for the platform, which is why removing it was treated as its own decision.

Decision

Build rostering as a constraint-solver problem with explicit legal and agreement rules and a stated objective. Separately, collapse the four co-deployed services into one and retire the cluster and the message bus.

Why

The first half is not an original conclusion and was not presented as one: bus driver rostering under hard legal limits is a well-established constraint-programming problem, and a solver guarantees what a learned model can only score. The second half is what the engagement was actually worth. A cluster, a message bus, two databases and six services were supporting one team, one deployment cadence and no independent scaling. The monthly bill exceeded the estimated value of the rostering problem itself. The two were gated separately, so the platform decision had to stand on its own evidence rather than arrive in the slipstream of a project everyone already wanted.

Why not the alternatives

  • Machine learning over historical rosters: Cannot guarantee a legal limit, and would reproduce the historical unfairness that prompted the request.
  • Buy a rostering product: Priced and taken seriously; rejected because the local agreement is the awkward part and would have become permanent customisation.
  • Leave the inherited platform as it is: The monthly run cost exceeded the estimated value of the rostering problem itself, for four services that have never deployed or scaled independently. Nothing in the estate pointed at a requirement.

Trade-offs accepted

  • Someone has to state the objective and defend it. Software cannot avoid that conversation, only delay it.
  • Collapsing the services is work with no visible feature at the end of it.

Reversibility

low reversibility

Constraints written down in one place are the most portable asset the operator could own. They outlive whichever solver is used. The platform removal was staged so each step could be halted.

Complexity budget

Kubernetes, a message bus, two databases and six services supported one team, one deployment cadence and no independent scaling. None of it pointed at a requirement. The rostering work was sequenced behind the removal so the new code did not inherit the estate.

Non-functional requirements

  • No roster may be published that breaches a hard constraint, enforced rather than scored
  • A roster must be explainable to the driver it affects
  • Rostering must run without the platform engineer being available

Decision gate

GOPAUSESTOP

GO on the solver, and a separate explicit GO on removing the platform, deliberately not bundled so the second could be argued on its own evidence.

Implementation

Constraints written down and agreed with union representatives before any code. A solver producing rosters correct by construction. Services merged one at a time, cluster retired last.

What the decision was expected to achieve

Rosters produced in minutes rather than days, no unlawful roster reaching publication, and a materially smaller monthly platform bill. Overtime hours and constraint violations at publication are the measures.

No outcome is claimed. This is an illustrative example, so there is nothing measured to report, and a real engagement would state what happened and how it was verified.

Lessons

  • If the rules are hard limits, you want a solver. That is settled practice in this field, not an insight. Knowing which of your conclusions are settled is part of the job.
  • The expensive problem is often the estate you inherit, not the one you were asked about. Nobody had priced the platform because nobody had been asked to.
  • Gate unrelated decisions separately. Bundling a contested decision with an obvious one buys the contested one a free pass.
  • Write the constraints down. They are the durable asset. The algorithm is replaceable.

Free · 30 minutes · one real problem

Bring a problem. Leave with clarity.

Thirty minutes, one real problem, structured thinking. If there's no value, there's no engagement.