National vaccination, Panama
In a vaccination campaign the queue is not an inconvenience, it is part of the clinical protocol.
- When
- 2021
- With
- XPLOR, CTO, Fluyapp platform, AstraZeneca, national rollout, public health
As CTO of XPLOR I was responsible for the platform behind the AstraZeneca vaccination rollout in Panama, built on the Fluyapp queue engine.
The full flow of a vaccination centre
This is not “book an appointment”. The system governed each person’s entire path through the centre, across several sites at once and in real time:
- the appointment and the arrival,
- the call to the right station,
- the dose,
- and the post-vaccination observation: the fifteen minutes a citizen must remain on site, monitored.
That last step changes the problem. In any other setting, whoever has been served walks out and stops being your responsibility. Here they are still inside, you need to know exactly when their observation started and when they may leave, and the station that just freed up already has someone waiting for it.
Why this is not queue management
A vaccination campaign is paced from the outside: vials arrive when they arrive, once opened they have a window of hours, and the goal for the day is not to serve whoever showed up nicely — it is not to waste doses. The queue stops being a matter of comfort and becomes the instrument by which a health protocol is met, or missed.
And there is no rehearsal. A vaccination centre opens at a set hour, with people queuing outside since before dawn, in the middle of a pandemic. The system works that day or it does not.
What it left behind
The same lesson as the Electoral Tribunal, in a different register: when software operates in the physical world with a person waiting in front of it, availability is not a dashboard metric — it is the product.
The state that matters
Modelling the centre as a single queue — the one for service — is the mistake that fills the room without anyone noticing. The station frees up; the person does not.
// A vaccinated citizen has NOT left: they are under observation. Two
// different resources with two different clocks, and conflating them is
// what saturates the room while every station sits empty.
type State =
| { phase: 'waiting' }
| { phase: 'at_station'; station: StationId }
| { phase: 'under_observation'; since: Instant; freeAt: Instant }
| { phase: 'discharged' };
const OBSERVATION = minutes(15); // clinical protocol, not a courtesy
function administerDose(c: Citizen, now: Instant): [State, Event[]] {
const freeAt = add(now, OBSERVATION);
return [
{ phase: 'under_observation', since: now, freeAt },
// Two things at once, which is why there are two events: the station
// returns to the available queue, and the room deducts a seat until
// the observation window closes.
[Event.stationFree(c.station), Event.seatTaken(c.id, freeAt)],
];
}
From this comes the real constraint of the day: the stations do not set the pace. The observation room’s capacity divided by fifteen minutes does.
Write to me
If you are thinking about building something with AI and want to talk it through with someone who has put it into production, write to me. I answer myself.
hola@giron.ai