A pension enrolment assessor on AWS for a few dollars a month
A hospitality group with four sites and 212 people on its payroll had its pension duties set up the way most employers do: the payroll software’s pension module, switched on years ago and trusted since. In July a kitchen porter asked why a friend at another site had a pension deduction and they did not. The answer took a fortnight to find and was worth £8,012.

Key takeaways
- The duty to enrol is tested every pay period, on the earnings paid in that period.
- A worker on variable hours can cross the trigger one week, fall back the next, and stay in.
- Every deadline hangs off the date a duty arose, so that date is the most important field.
- The system reads staff messages and routes them. It never opts anybody out.
- 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.
- Security & identity
- Analytics
- Front-end & mobile
Why this goes wrong in a business that is otherwise well run
Because the rule is simple to state and awkward to apply to a rota. Workers aged from 22 up to state pension age are automatically enrolled when their earnings go over a trigger. Stated like that it sounds like something you check once, at the start. It is not. The test is applied to the earnings paid in each pay reference period, which for a weekly payroll means fifty-two separate tests a year for every person on it.
A salaried manager on £31,400 passes every one of those tests identically, so for an office the one-off view happens to work. A kitchen porter contracted for twelve hours and working anything from nine to twenty-two does not, and a hospitality or care workforce is mostly people like that. An employer whose duties were set up by reading contracts has set them up for a workforce it does not employ.
In the worked example the pension module had been configured to assess on contracted hours. Twelve hours at £12.85 is £154.20 a week, under the weekly trigger every week, forever. It was the one configuration under which the module could never be wrong and never be right.
What runs (the inside)
- Assessment. Every worker, every pay run, against the thresholds in force for that period, with the reason written down. Part 2.
- Postponement. A dated decision with a notice attached, not a setting in the payroll. Part 3.
- Messages. What staff write about the pension, classified and routed to the right process by fixed replies. Part 4.
- Opt-outs and re-enrolment. The window that opens after enrolment, the refund it can lead to, and the cycle that comes back every three years. Part 5.
One December, four sites
- Management
- Analytics
- People
In plain words
Each pay run produces an export: who was paid, how much, for which period. The system parses it and assesses every worker on it. Age comes from a date of birth rather than a stored age, because 22 arrives on a birthday rather than in April and state pension age depends on when somebody was born. Earnings are what was paid in the period, including the overtime and the bonus that happened to land that week.
The assessment produces one category per worker and stores the reason with it: eligible jobholder, non-eligible jobholder, entitled worker, or already an active member with nothing to assess. That last one matters more than it looks, because a worker enrolled in December whose pay drops in January stays enrolled.
When an assessment creates a duty the system records the date it arose, because that date is what everything else hangs off: the six weeks to enrol and write, the opt-out month that follows, the refund a valid opt-out leads to. A deadline computed from the wrong date is a deadline missed on schedule.
Separately, staff write in. Most of it is questions. Some of it is somebody saying they do not want the pension, and how that message is handled is the one place in this system where being helpful is the wrong instinct.
Design rules that shaped every decision
- Assess on earnings paid in the period, never on contracted hours.
- Thresholds are dated rows per pay frequency, not an annual figure divided in code.
- Every duty records the date it arose and the assessment that created it.
- Postponement is a decision a person makes, with a notice sent, never a default.
- The system never supplies an opt-out notice or writes anything that reads as a nudge to leave.
- An assessment is never edited. A corrected pay run produces a new one that says what it replaced.
What it does not do
It does not run the payroll or calculate the deductions. The payroll software does that well; what it did badly was decide who should be in. This system produces enrolment instructions and the evidence behind them.
It does not choose the pension scheme or check that it qualifies. That decision is taken once, with an adviser, and does not change from one pay run to the next.
And it does not tell anybody whether to stay in. Workers ask, and the honest answer from an employer is that it cannot advise them and the scheme can explain what leaving means. The system gives that answer every time, including when it feels unhelpful.
The next four posts walk through each piece: the assessment that one extra hour can change, postponement as a decision with a date on it, what a message about leaving is allowed to become, and the windows and the three-year cycle that follow enrolment. One diagram per post, a cost breakdown, and an engineering reference at the end.
All posts