An access review reporter on AWS for a few dollars a month
Every business past about fifteen people has accounts it does not know about: the designer who left in March whose file storage login still works, the shared account three people use, the contractor added to something in 2023. None of it is negligence; it is that nobody has ever assembled the list, because assembling it means logging into eleven admin panels. This post walks through a small system that assembles it weekly.

Key takeaways
- One user list per service, collected weekly where an API exists and manually where it does not.
- Every account is matched against the current staff list, which is the whole leaver check.
- Each service has one named owner, and the review asks them rather than everybody.
- It cannot remove access. Knowing is the hard part; removing is thirty seconds.
- Designed on AWS for about $1 a month.
The whole system on one page
Before any code, here is the shape of what we are designing.
- Database
- Analytics
- People
- Outside AWS
Two different jobs
There are two things people mean by access review and they need completely different cadences. One is “has anybody kept access they should not have”, which is a leaver question and needs to run weekly. The other is “does everybody still need what they have”, which is a judgement question and cannot usefully be asked more than twice a year without becoming a rubber stamp.
Conflating them produces the standard failure: a quarterly review where somebody approves four hundred rows in six minutes, which satisfies an auditor and catches nothing. Separating them means the automated half runs constantly and the human half is short enough to be done properly.
What runs (the inside)
- The collector. Pulls the user list from each service that has an API, weekly, and stores it as a dated snapshot. Part 2 covers the services with no API, which in a small business is usually about half of them.
- The matcher. Maps each account to a person on the staff list, or to nobody. Part 3 is about why that matching is harder than it sounds and what to do about shared accounts.
- The reviewer. Two outputs on two cadences: an immediate leaver report, and a twice-yearly review where each owner sees only their own service. Parts 4 and 5.
One account, end to end
- Database
- App integration
- Management
- Analytics
- People
In plain words
A business of about thirty people pays for fourteen services. Nine have an API that will list users; five do not. The first collection produces two hundred and eleven accounts across the nine, which is already more than anybody expected for thirty people.
Matching against the staff list, one hundred and seventy-two belong to current staff, twenty-two are shared or service accounts, and seventeen match nobody. Of those seventeen: eight are former employees, four are contractors whose engagement ended, three are test accounts somebody created, and two are people who joined under one email address and now use another.
That first report is the valuable one and it takes an afternoon to work through. After that the weekly run finds one or two a month — usually somebody who left last week and whose file storage was missed — and each takes about a minute. The twice-yearly review is a separate, much shorter conversation about whether current staff still need what they have.
Design rules that shaped every decision
- Leavers weekly, entitlements twice a year. They are different questions with different cadences.
- One owner per service, and the review asks only them about only their service.
- It never removes access. An incomplete account list is a bad basis for revocation.
- Services with no API are tracked as unverified and counted, rather than left out.
- A shared account is a finding in itself and is never matched to a person.
- Every snapshot is kept, so “who had access on this date” is answerable.
Why this shape
Access review is a compliance exercise in most businesses and a genuinely useful control in very few, and the difference is entirely whether the list is real. A review that asks somebody to approve a list assembled by hand six weeks ago is theatre; a review of a list collected on Monday is a control.
So this design spends almost everything on collection and matching, and almost nothing on the review workflow. There is no approval chain, no evidence pack and no attestation record beyond who answered what and when — because the auditor’s question and the security question have the same answer, and only one of them requires ceremony.
The next four posts walk through each piece: how the lists are collected, how accounts are matched to people, how the twice-yearly review runs, and how leavers are caught. One diagram per post, a cost breakdown, and an engineering reference at the end.
All posts