All articles Technology

How We Teach OSCAR to Account for Traffic, Job Complexity, and Worker Fatigue in a Single Booking Slot

João Marques
Map of Porto with route optimization lines and scheduling data

A plumber finishing a boiler service call in Matosinhos at 14:20 has, on a standard Tuesday afternoon, approximately 38 minutes of travel time to reach Foz do Douro through the IC1. If we schedule that plumber for a 15:00 job in Foz, we are creating a 2-minute theoretical margin for the journey — before accounting for parking, the walk to the building entrance, and the possibility that the Matosinhos job runs 15 minutes over. It will not work. We know it will not work. The homeowner in Foz will wait, and the plumber will be stressed for the rest of the afternoon.

The scheduling challenge in home services is not conceptually different from logistics routing — it just gets less attention because it happens one appointment at a time rather than in visible fleet operations. Each decision in our scheduler is making or breaking the reliability of a real person's afternoon. That focus is what drove how we built the three-factor model that OSCAR uses today.

Factor 1: Real travel time, not map distance

The naive approach to scheduling is to calculate driving distance and apply a flat speed estimate. That works on empty roads. Porto is not an empty road. The VCI through the city centre on a Friday afternoon is not the same road as the VCI at 10:00 on a Tuesday. The approach along the Ponte da Arrábida from Gaia to Porto in the morning and returning in the evening are predictably different conditions.

Our travel time model pulls traffic data to build time-of-day and day-of-week travel matrices between Porto's postal zones. When the scheduler evaluates whether a professional can make a transition from job A to job B, it queries the matrix for that specific hour and day combination rather than using a static distance estimate. For the Matosinhos-to-Foz transition at 14:20 on a Tuesday, the answer is 38 minutes. For the same transition at 17:30, the answer is 54 minutes, because the IC1 southbound into Porto from Matosinhos typically congests after 17:00.

We also add a buffer on top of the travel estimate. Currently that buffer is 8 minutes for standard transitions and 15 minutes for transitions that cross the Arrábida or Freixo bridges, where bottlenecks are structural rather than time-of-day variable. These numbers came from the first six weeks of live operations — we tracked actual transition times against predicted times and calibrated accordingly. We will keep calibrating. The current buffer values are not final.

Factor 2: Job complexity scoring

Job duration variance is the scheduling problem that most home services platforms get wrong. A "tap replacement" can take 45 minutes in a modern apartment in Bonfim with standard plumbing fittings. The same category job in a 1940s building in Miragaia with corroded valve seats and non-standard pipe diameters can take 2.5 hours and require a parts run. If the scheduler allocates a fixed 60-minute slot for all tap replacements, it will be wrong systematically in one direction or the other.

Our job complexity score is a weighted estimate generated at booking time. The inputs are: job category and sub-category (tap replacement vs drain unblocking vs boiler service), the homeowner's text description of the problem, building age if we have it from address data, and historical job duration for similar jobs in the same postal zone. The score translates into a base duration estimate plus a variance band.

For a standard tap replacement booked in a post-2000 building in Cedofeita, the base estimate is 55 minutes with a variance band of ±15 minutes. The scheduler allocates a 75-minute slot. For the same category in a pre-1960 building, the base estimate is 80 minutes with a variance band of ±25 minutes, and the scheduler allocates a 110-minute slot. Those extra 35 minutes cost the professional one fewer job in a given day, but they cost the system far less than a cascading delay that derails three subsequent bookings.

We don't yet have good complexity scoring for tile work — that category launched six weeks ago and we have limited historical duration data. Currently we're using conservative flat estimates with wide variance bands, which means we're probably over-allocating time for simple tile repair jobs. We'll correct this as data accumulates, but we'd rather over-allocate and be reliable than under-allocate and fail delivery.

Factor 3: Worker state across the day

This is the factor most scheduling systems ignore entirely. A plumber at 09:00 is not the same as a plumber at 16:30 after four jobs, two of which ran over. Work quality in trades declines meaningfully in the final hours of a long day — not because professionals are careless, but because physical tiredness affects precision work. A rushed final job at 17:45 after a full day is higher-risk for both the professional and the homeowner.

We handle this with a job-count and hour-count cap per professional per day. The caps are currently 6 jobs or 7 billable hours, whichever comes first. A professional who has already completed 5 jobs by 15:00 will not be scheduled for a 6th job that would push them past 7 hours, even if travel and timing would technically allow it. They can accept optional evening bookings through the app, but the automated scheduler will not push work onto them past that threshold.

We arrived at 6/7 empirically. In the first month of operation we saw that professionals completing more than 6 jobs in a day had a meaningfully higher rate of post-job notes from homeowners about "rushed feeling" or "left before explaining the work." The 6-job cap reduced that pattern significantly. We have not published those numbers because the sample is still too small to make statistically meaningful claims, but the directional signal was strong enough to implement the cap operationally.

How the three factors interact in a single booking decision

When a homeowner in Paranhos books a drain unblocking for 13:00 on a Wednesday, the scheduler runs a candidate selection: which professionals in the network are (a) certified for plumbing, (b) not currently booked at 13:00 or in an active job that would end too close to 13:00, (c) within reachable travel distance by 13:00 given current job locations, and (d) under their daily cap. From that candidate pool, it ranks by proximity and professional rating for that job category.

The result is not always the highest-rated professional overall — it is the highest-rated professional who can genuinely be there at 13:00 and do good work. A plumber with a 4.9 rating who is currently in Espinho with two more jobs in Gaia before 13:00 does not appear in the candidate pool. A plumber with a 4.6 rating who finished a Campanhã job at 11:45 and is 12 minutes from Paranhos is the correct match.

We have been asked whether the weighting of these factors is fixed or whether it adapts automatically. Currently the weights are manually calibrated based on operational data and reviewed every two to three weeks. We are not running a fully self-adjusting system. The risk of a self-adjusting system without robust oversight is that it optimizes for the wrong metric — for example, maximizing daily job count at the expense of job quality or professional wellbeing. We want to understand what we're optimizing before we hand the tuning knobs to an automated loop.

What the model does not yet do

We want to be specific about the current limits. The model does not account for weather meaningfully. An Atlantic storm pushing up the coast in January can add 15-20 minutes to journeys across the Arrábida and the Freixo bridges as the city's older cobblestone streets in Miragaia and Bonfim flood at kerb level. We have those events flagged for manual override when forecast precipitation exceeds certain thresholds, but we don't yet have an automated weather-adjustment layer in the scheduler.

The model also does not account for professional preference. A plumber who lives in Matosinhos and prefers jobs in the western zones — Foz, Nevogilde, Matosinhos — will still be scheduled into Paranhos or Campanhã if they're the best available match by the other criteria. We are building a preference declaration system that will let professionals specify their preferred working zones, which feeds into candidate ranking as a soft weight. That is not live yet.

The three factors we have are a substantial improvement over no coordination system at all. Each generates real operational reliability that we can measure in on-time arrival rates and same-day completion rates. We will add more inputs as we understand the problem better, not before.