Home / Work / Case study

Beanfield · Aug to Oct 2026

Guide migration and recording repair

Changing the TV guide provider silently breaks every customer's series recordings, because each rule points at a programme ID that no longer exists. I led the migration, repaired the broken rules at scale, ran the v2 guide cutover and automated the daily re-key.

My roleMigration lead and repair owner
Repaired1,636 of 1,661 rules (98.5%)
Cutover day2,131 rules re-keyed in one day
NowDaily guarded job at 06:15

The problem

A series-recording rule says "record every episode of programme X". X is an ID from the guide provider. Move to a new provider and the rules point at shows that no longer exist: customers quietly stop getting their recordings.

  • 11,972 standing rules sat on 26 channels still to move, 11,962 of them on just 14 channels (11 Aug 2026).
  • 1,133 superseded rules were still alive across 542 accounts.
  • After the move, the new provider rebuilds its guide every night and changes IDs again: 39 to 344 rules went stale per day (7 to 17 Oct), out of about 6,300.

The migration

  1. Agreed the method on 4 Aug 2026: move channels in batches by changing each channel's external ID and running the import by hand.
  2. Joined the vendor channel list to the platform master list: 194 set up, 10 paused, 184 live; 156 migrated and 26 left by 11 Aug.
  3. Verified every batch with a read-only script against the platform's read API before moving on.

The repair campaign (from 12 Aug)

  1. Built a repair runner with priority tiers: B1 airing in the next 72 h, B2 in 3 to 7 days, B3 in 7 to 12 days, B4 no date.
  2. Preflight checks abort a repair rather than guess; every write lands in a ledger and a change register with verify and reverse.
  3. Overnight wave of 12 to 13 Aug: B2 599 fixed, B3 78 of 88, zero degraded aborts, nothing cancelled.
  4. Campaign result: 1,636 of 1,661 rules on active accounts fixed (B1 842 of 851, B2 706 of 711, B3 88 of 88). 1,960 rules in place across 721 accounts and 8,197 hours of recording space re-reserved.
  5. Audited my own ledger: 118 of 119 rules logged as "write failed" had in fact been created.

The v2 cutover, 29 Sep 2026

  • New guide file delivered at 03:41 (about 72 MB); import 04:10 to 06:11, 64,312 programmes, 0 errors.
  • Post-import checks: 12,114 of 12,200 guide rows updated in place, 0 double loads.
  • Detector proposed 2,295 creates and 3,198 cancels; a liveness filter dropped 1,603 dormant and 96 inactive rules first.
  • 2,131 rules created that day; at the evening audit 2,066 were current.

Turning the fix into a daily job

  • A scheduled job at 06:15 re-keys the rules the nightly guide import breaks.
  • Guard rails: at most 400 creates a day, dry run first, and it holds itself when more than 10 creates (or 10%) are refused at the dry run; a held report carries the manual commit command.
  • Measured before redesigning: re-key cannot start earlier because the import ends between 05:58 and 06:12; an offline planner predicted 746 of 761 overnight breaks (98%); the commit saves 15 to 20 minutes a day. Stable IDs can only come from the provider.

What was hard

  • The only write path is the web-player API, and every write creates a web terminal that must be removed afterwards.
  • 25 rules could not be fixed because the live programme ID was ambiguous; the runner refused to guess.
  • Channel counts differ by source (177 on the vendor list, 207 on the platform in August, 193 in the master list), so every count is stated with its source.
Reusable pattern: dry run, then commit; preflight aborts; a register row with verify and reverse for every write; measure the pipeline before redesigning it.

Stack

SmartTUBE SDP admin APISimplyTV guide XMLnPVRWeb-player (WebOS) APIPython runnersCSV ledgerssystemd timers