A training reminder bot on AWS for a few dollars a month
Required training is a problem that looks solved and is not. Somebody keeps a spreadsheet, everybody does their induction, and then two years pass. In that time four people changed roles, six refreshers came due, and two new starters joined during a busy month. Nobody was negligent; the spreadsheet just has no way to notice any of that. This post walks through a small system that derives the requirements rather than storing them.

Key takeaways
- Requirements are derived from the role, so a role change recomputes them automatically.
- A completion with a validity period generates its own next assignment.
- The system tracks that training happened. It has no opinion about how it was delivered.
- Nothing is marked complete by the system. A person confirms, and it is recorded who.
- Designed on AWS for about $2 a month.
The whole system on one page
Before any code, here is the shape of what we are designing.
- App integration
- Analytics
- People
Derived, not stored
The obvious model is a list per person of what they need. It works on the day it is built and decays from then on, because when a requirement is added to a role, somebody has to go and add it to every person in that role, and that is exactly the step that does not happen.
So requirements live once, against roles, and a person’s list is computed. Adding manual handling to the warehouse role assigns it to everybody in the warehouse that afternoon. Moving somebody from warehouse to delivery recomputes both lists. Neither requires anybody to remember anything, and that is nearly the whole value.
What runs (the inside)
- The requirements engine. Takes a person’s role, plus any site or equipment attributes, and produces their required training list. It runs on a schedule as well as on change, so a requirement added in the sheet takes effect without a deploy or a trigger.
- The assigner. Creates an assignment when a requirement appears that has no valid completion. Three causes: somebody joined, somebody’s role changed, or a completion expired. The third is most of them after the first year.
- The chaser. Nudges the person, then their manager, then reports the gap weekly. It is deliberately gentle about individual chasing and quite direct about the aggregate, because a training gap is a management problem rather than a personal failing.
One requirement, end to end
- Machine learning
- Management
- People
In plain words
A new warehouse operative joins in March. The requirements engine reads their role and produces four requirements: manual handling, fire safety, the site induction and abrasive wheels. None has a valid completion, so four assignments are created on their first day, each with a due date from the requirement’s own grace period — the induction is due day one, manual handling within two weeks, abrasive wheels within a month.
Three of the four are done in the first fortnight and their supervisor confirms each one. Abrasive wheels is not, because the course is monthly and the next one is the 14th. The chaser nudges at the due date, then tells the supervisor at a week over, and the person appears in the weekly gap report until it is done. Two years and eleven months later, the manual handling completion approaches its three-year validity, an assignment appears, and the whole cycle repeats without a single human having thought about a date.
Design rules that shaped every decision
- Derive requirements from roles. A stored per-person list is correct on the day it is written and decays from then on.
- A completion with a validity period schedules its own successor. Refreshers must not depend on memory.
- Never mark anything complete automatically. A completion is a claim somebody makes, and the record says who made it.
- Chase people gently and report the aggregate directly. A training gap is a management problem.
- A requirement removed from a role becomes not-required, not deleted. Past completions still matter.
- Grace periods belong to the requirement. An induction is due on day one; a course that runs monthly is not.
Why this shape
Training tracking is one of those problems where the data is easy and the maintenance is everything. Any spreadsheet can record who did what. The difficulty is that the right answer changes constantly for reasons nobody notices — a role changes, a requirement is added, three years pass — and each of those changes requires somebody to go and update rows by hand.
So the design removes the per-person list entirely. There is a role-to-training mapping, a set of completions, and everything else is computed on a schedule. The system has almost no state of its own, which is why it is still correct two years after anybody last thought about it.
The next four posts walk through each piece: how requirements are derived, how assignments are created, how completions get recorded, and what the gap report shows. One diagram per post, a cost breakdown, and an engineering reference at the end.
All posts