Election 2029: Models and Reality

On January 15th 2026, Robert Jenrick broke my election site.

Okay, that’s slightly hyperbolic. The site continued to operate, and it would be fairer to say that the actions of Kemi Badenoch and Robert Jenrick exposed a flaw in the data modelling in my site.

For those readers who don’t follow UK politics, two events happened on January 15th. In the morning, Kemi Badenoch (the leader of the Conservative party) withdrew the whip from (i.e. kicked out) Jenrick, previously a Conservative MP, on the ground that she had evidence he’d been preparing to defect to Reform UK. In the afternoon, Jenrick then did defect to Reform UK. (Strictly speaking at that point I guess it wasn’t a “defection” as such; he just joined Reform UK from a temporary position of not being a member of any party.)

The election site is able to handle party changes in general – there have been several since 2024 which have gone without a hitch. One adjustment needed to be made when Mike Amesbury resigned, at which point the Runcorn and Helsby constituency had no representation until Sarah Pochin won the by-election there, but that’s all.

It would have been fine if Badenoch had withdrawn the whip on the evening of January 14th and then Jenrick had defected on January 15th… but the site couldn’t ingest data representing a single person changing party twice in one day. It’s not an unreasonable thing to happen, but it caused problems when it did happen, such that I couldn’t update the site data to show the ejection+defection. (Again, the site remained active, and I could still add polls etc – I just couldn’t make the site data represent this specific pair of events.)

In the end, I had to change three bits of code to get it working, all of which assumed there’d be at most one party change per day:

  • The code in the “refresh external data” tooling that processes the data from the Parliament Members API, filtering and transforming it into “just what we need, in a useful format”
  • The code in the “prepare a new data context” tooling that joins that data with a hand-maintained data file providing descriptions for party changes (e.g. “Whip withdrawn”, “Whip restored” etc)
  • The code in the web site code itself that processes the data context – in this case, working out who is currently representing each constituency and on behalf of which party (think of it like replaying a transaction log of changes since the 2024 election)

Fixing all of these wasn’t terribly difficult – no more than an hour’s work, probably less – but it did make me wonder where else my model didn’t match reality, in a dangerous way.

In most cases, we shouldn’t expect our data models to be absolutely in line with reality. There are simplifications which are “mostly harmless” and the cost of more accurate modelling would vastly outweigh the benefit. As an example outside the election site, I strongly suspect that very few line-of-business applications take account of leap seconds. But it’s nice to know when you are simplifying reality, so you can perform an appropriate risk assessment.

In this case, I believe when I wrote the code to handle party changes I just didn’t even consider the possibility of two changes in a day, even though it’s not that strange a thing to happen. There are other aspects where I have consciously simplified things, sometimes in a slightly ad hoc manner. (For example, how the Speaker’s constituency is represented in seat projections varies by pollster, and I haven’t gone to the effort of modelling that faithfully.)

As it happens, even after the fixes I’ve made, I still couldn’t handle three party changes in one day (for one MP) – but going further would take a fair amount more work. The relevant data from the Parliament API is an unordered set of “party X from date Y to date Z” entries, effectively (with gaps during elections). For two changes on one day, that’s fine – we have three entries, e.g. for Jenrick:

  • Conservative from July 4th 2024 to January 15th 2026
  • Independent from January 15th 2026 to January 15th 2026
  • Reform UK from January 15th 2026 to present day

Ordering the entries by start date then by end date provides a properly-ordered list… but only so long as the (start, end) pairs for each entry are unique. If we had three changes on the same day, that would mean four entries, two of which would have the same start and end date. At that point, the Parliament API data on its own would be insufficient to figure out the correct ordering.

I’m not worried about this – if it happens, the cost will be scrabbling to figure out a way to ingest the data appropriately. I believe the fix for the last two of the three issues above would still already work – it would be a matter of adding some extra (hand-maintained) information to help with the ingestion. But I also think that’s vastly less likely than another day like January 15th occurring, with two changes.

Conclusion

For me, the lessons from this are:

  • Try to make yourself aware of the ways in which your data model (or data processing) makes assumptions about reality which may not turn out to be correct
  • Perform a risk assessment of those gaps between the model and reality
  • Document any gaps where the risk isn’t worth the cost of addressing the gap
  • Always be aware that there may be gaps you haven’t identified

Leave a comment