AI in a Startup
The self-styled uber AI order maker resolves to FirstOrDefault behind an in-source confession, and its reservation heuristic structurally out-bids every earlier booking - the estate's data-science audit, written up as the short honest piece its eleven lines deserve.
Every estate audit I run keeps a data-science lens, and most codebases fail it the boring way: no models, no features, nothing to report. Pacco fails it in a way I have never seen anywhere else — loudly, on purpose, with a comment that names the whole genre. Part 9 traced OrderMaker's Chronicle saga end to end and deliberately skated past the two lookups where the orchestrator goes shopping: the best vehicle for an order, and the best date to reserve it. This part reads those lookups in full, because they are the estate's entire machine-learning story, and because the honest answer to “where is the AI?” turns out to be one of the best teaching artefacts in all thirteen repositories.
The promise at the front door
Pacco.Services.OrderMaker introduces itself at its root route, in Program.cs:
.Get("", ctx => ctx.Response.WriteAsync("Welcome to Pacco uber AI order maker Service!"))
Uber AI order maker. Take the phrase at face value for a moment, because plenty of product copy asks you to. An AI order maker would imply a ranking model over vehicles — capacity fit, variant match, price, utilisation history — and some optimisation over the reservation calendar. It implies features, training data, inference, and someone who worries about drift. Hold that expectation while we open the two classes that deliver on it.
The best vehicle, according to the machine
Here is VehiclesServiceClient.GetBestAsync, quoted whole from Pacco.Services.OrderMaker/Services/Clients/VehiclesServiceClient.cs, because the implementation is the story:
public async Task<VehicleDto> GetBestAsync()
{
var vehicles = await _httpClient.GetAsync<PagedResult<VehicleDto>>($"{_url}/vehicles");
var bestVehicle = vehicles?.Items?.FirstOrDefault(); // typical AI in a startup
if (bestVehicle is null)
{
throw new InvalidOperationException("The best vehicle was not found.");
}
return bestVehicle;
}
Read it slowly, because every line teaches something.
The query carries no criteria. GET /vehicles with no filters, no sort, no paging parameters — so Vehicles returns page one at the default page size, in whatever order Mongo happens to return unindexed documents. The candidate pool for “best” is “the first page of everything”.
FirstOrDefault() is the model. Best means first. Not cheapest, not the right variant for a parcel of weapons or organs, not the one with a free calendar — first. The order's parcels are never consulted; the saga has their ids in hand and asks for none of their properties.
The comment is the documentation. // typical AI in a startup is a real comment in real source, and it is doing more work than most architecture decision records I have read. It tells you exactly what this method is, exactly what it is standing in for, and exactly how seriously to take the greeting at the front door.
The exception message keeps the bit going. “The best vehicle was not found” — the failure mode of an empty page one, reported in the vocabulary of a ranking that never happened.
The method's name is the part I would flag in review. GetBestAsync returning VehicleDto is indistinguishable, at every call site, from a genuine ranked choice. The saga logs Found a vehicle with id: '{vehicle.Id}' for {vehicle.PricePerService}$ and moves on, and nothing downstream can tell that “found” meant “took the first one”. A heuristic is fine; a heuristic wearing a model's name is a small lie that every caller repeats. GetFirstAvailableAsync would have cost nothing and told the truth.
The reservation optimiser
The second half of the intelligence lives in ResourceReservationsService.GetBestAsync, also quoted whole:
public async Task<ReservationDto> GetBestAsync(Guid resourceId)
{
var resource = await _availabilityServiceClient.GetResourceReservationsAsync(resourceId);
if (resource is null)
{
throw new InvalidOperationException($"Resource with id: '{resourceId}' was not found.");
}
var latestReservation = resource.Reservations.Any()
? resource.Reservations.OrderBy(r => r.DateTime).Last()
: null;
if (latestReservation is null)
{
return new ReservationDto
{
DateTime = DateTime.UtcNow.AddDays(1),
Priority = 0
};
}
return new ReservationDto
{
DateTime = latestReservation.DateTime.AddDays(1),
Priority = latestReservation.Priority + 1
};
}
The whole policy: if the vehicle has no bookings, propose tomorrow at priority zero; otherwise find the latest-dated booking and propose one day after it, at one priority higher. Two properties of that policy are worth sitting with.
The calendar only ever extends. The heuristic never looks for a hole. If a vehicle is booked next Monday and next Friday, the gap in between is invisible — the proposal is Saturday, one day past the latest booking. Every order pushes the frontier out by exactly one day, so a popular vehicle's next available date recedes at one day per order regardless of how empty its actual calendar is.
Priority ratchets upward forever. Each proposal carries latestReservation.Priority + 1. After thirty machine-made orders on one vehicle, the newest reservation sits at priority thirty or so — not because any order was important, but because twenty-nine came before it. Priority stops encoding importance and becomes a booking counter.
That second property has teeth, because of what priority means on the other side of the wire.
The auction the machine cannot lose
Availability's Resource.AddReservation — the aggregate that receives the saga's ReserveResource command — resolves same-date collisions by priority, and evicts the loser:
// Pacco.Services.Availability.Core/Entities/Resource.cs (trimmed)
var hasCollidingReservation = _reservations.Any(HasTheSameReservationDate);
if (hasCollidingReservation)
{
var collidingReservation = _reservations.First(HasTheSameReservationDate);
if (collidingReservation.Priority >= reservation.Priority)
{
throw new CannotExpropriateReservationException(Id, reservation.DateTime.Date);
}
if (_reservations.Remove(collidingReservation))
{
AddEvent(new ReservationCanceled(this, collidingReservation));
}
}
A strictly higher-priority newcomer expropriates the incumbent; the evicted reservation raises ReservationCanceled, and downstream that cancels the incumbent's order. Now put the two halves together. The saga's proposal always carries a priority strictly above the highest-dated booking it just read. On a quiet resource it also proposes an uncontested date, so nothing collides and nobody notices. But the moment a collision does happen — two sagas racing for the same vehicle on the same day, or a customer who booked that date directly through the gateway at an ordinary priority — the machine's bid wins by construction. The “AI” cannot lose an auction against anything booked before it; it can only be refused by an even later bid, which, if it comes from OrderMaker, will carry a higher number still. An escalation loop, assembled from two innocent-looking heuristics in two different repositories, with a customer's cancelled order as its exhaust. The expropriation invariant itself — who wins, who gets bumped, and the compensation cascade behind it — is told from the domain's side in the reservation that bumps you.
The ruling, honestly
My audit method says a lens earns its place by finding nothing, so here is the data-science finding for the whole estate, recorded formally: there is none. No models, no feature engineering, no training or inference code, no evaluation, no data pipeline feeding anything that learns — across thirteen repositories, the sum total of machine intelligence is the eleven-line method with the confession in it and the plus-one arithmetic above. That is not a criticism of a 2020 teaching estate; a parcel marketplace demo has no business shipping a ranking model. It is worth writing down, because absences you never record become capabilities everyone assumes.
To be fair to the authors — and this is the part I genuinely admire — the satire is theirs, not mine. They wrote // typical AI in a startup into the source. They named the service “uber AI order maker” knowing exactly what was behind the curtain. The joke is self-aware teaching: this is what “our AI matches you with the perfect vehicle” looks like in most real products, except most real products hide the FirstOrDefault() behind a pitch deck instead of documenting it with a comment. The estate shows you the trick and the wires at the same time, which is more honesty than the industry norm.
What would the honest minimum have looked like, without a gram of ML? A scoring function: filter vehicles whose Variants cover the parcels' needs, prefer sufficient payload capacity, then cheapest — twenty lines, deterministic, explainable, and GetBestAsync would finally deserve its name. The distance between that and FirstOrDefault() is the distance between a heuristic and a placeholder, and the only thing bridging it today is a comment.
Three rules I took away:
- Name methods after what they do, not what the roadmap says they will do.
GetBestthat returns first is a defect in the API surface even when the behaviour is deliberate. - Record the absences. “No data science here, and here is the eleven-line stand-in” is a finding; an audit that only reports what exists will silently inflate what the label “AI” is worth.
- Check your heuristics for feedback loops before they meet an invariant. Neither
+1 daynor+1 priorityis dangerous alone; composed with an expropriation rule two services away, they form an auction rigged for the newest bidder.
Next, the audit widens from eleven lines to the whole estate: a smell audit with prescriptions — every finding pinned with its refactoring.guru name, and every name paired with the technique that cures it.