
Academy track
One place your numbers live

Your numbers pulled rather than logged into, landed raw, one identity per customer, and a report that arrives whether or not anything happened.
- 5 steps
- 6 hours in total
- A check you run at the end of every step
Step one is open to everyone, in full. No account, no card.
The other 4 steps are included in Membership, £79 a month.See Membership
By the end of this track you will have
- Step 1One scheduled task that pulls data out of one system, into a directory you own, with nobody opening a browser.
- Step 2Source data sitting unchanged in one table, and every tidy number you read built downstream from it.
- Step 3A map table that gives every customer one identifier of your own, and a query that returns their rows from three systems as one person.
- Step 4A short summary that arrives on a fixed schedule, to a named person, whether or not anything happened.
- Step 5A check per feed that knows when each one is late, and a report that prints the affected numbers as unverified instead of as a drop.
The running example
Every worked example follows one invented case from the first step to the last: a three-site café group.
Who it is for
Every Monday you log in to each system and copy the figures into a spreadsheet by hand.
Who it is not for
Not for you if one system already holds every number you look at. You do not have this problem yet.
The steps
Each one ends with a check you run yourself. The box is yours to tick when it passes.
0 of 5 steps ticked, kept in this browser
- Step 1.Pull, do not log in60 minutesOpen to everyone
Done means
Leave it for two scheduled runs, then run
ls -l /srv/hub/landing/billing/and see two files, different timestamps, both non-zero. Count the records in the newer one. If that count is exactly your page limit, pagination is not working and you have one page pretending to be a feed. - Step 2.Land it raw before you tidy it75 minutes
Done means
Run
select count(*) from raw_events where payload is null or source is null or fetched_at is null;and get 0. Then runselect count(*) from billing_charges;, drop the view withdrop view billing_charges;, recreate it from the block above, and run that count again. Same number, both times. If recreating the view changes an answer, something upstream of the view is being edited and raw is not raw. - Step 4.The report writes itself or it does not get read60 minutes
Done means
After two scheduled sends, two messages sit in your inbox. Put them side by side and compare the labels line for line. Every label matches, in the same order, including any line that was unverified in one and filled in the other. If the second message is missing a line the first one had, your template is being generated from the data rather than from the definition. That is how it hides things from you.
- Step 5.Know when the pipe broke75 minutes
Done means
Turn off one pull. Wait past its declared gap, run the check, and get exactly one row back naming that source with an age greater than its
max_gap_minutes. Run your summary. Confirm that source's numbers print as unverified rather than dropping towards zero. Turn the pull back on, wait one cycle, run the check again and get zero rows. If the summary showed a drop rather than the word unverified at any point in that test, you have a report that lies quietly. The rest of this track is worth nothing.
I keep this tick in this browser and send it nowhere. It goes when you close the browser.
Included in Membership
The rest of this track is included in Membership.
Step one is open to everyone, in full. Every step after it opens on a member account.
Included in Membership — £79/month.
What comes next
Your numbers live in one place now. Next is AI that reports on them in figures, not adjectives.
See all the tracks