Skip to content

Part 1 of 7 · Subscription audit bot series ~6 min read

A subscription audit bot on AWS for a few dollars a month

Every business past about eight people has a number it cannot state: what it spends on software a year. Not because the charges are hidden — they are all on the card statement — but because a statement is a flat list of hundreds of charges and a subscription is a pattern across months. The £14 that appears every month from a merchant nobody recognises is £168 a year, and there are usually eleven of them. This post walks through a small system that finds the patterns and asks one question about each of them, once a year, before it renews.

a large warehouse filled with lots of boxes
Photo by Arum Visuals on Unsplash

Key takeaways

  • One input: the card and bank feed you already export or already get emailed.
  • Charges are grouped into subscriptions by merchant, amount and interval — not by name alone.
  • Every subscription gets an owner and a purpose, or the lack of one becomes a question.
  • The only action is a question before a renewal. It holds no credentials and cancels nothing.
  • Designed on AWS for about $3 a month.

The whole system on one page

Before any code, here is the shape of what we are designing.

System: a card feed in, three pieces inside AWS, questions outThree boxes across the top sit outside the AWS account. On the left, Card and bank feed: the export or emailed CSV the business already receives. In the middle, Owner tab: the sheet recording who owns each subscription and why. On the right, Owners: the people who get one question a year. Each connects by an arrow to the AWS account container below. Transactions flow down into the account. The owner tab feeds in to say who owns what. The owners receive a keep-or-drop question. Inside the AWS account are three components in a row. On the left, the Grouper, which turns individual charges into subscriptions. In the middle, the Attributor, which attaches an owner, a purpose and an annual cost to each. On the right, the Asker, which sends a single question before each renewal. A note at the bottom says the system holds no credentials to any of these services and its only output is a question.AWS ACCOUNTCard + bank feedexport or emailed CSVOwner tabwho owns what, whyOwnersone question a yearGroupercharges intosubscriptionsAttributorowner, purpose,annual costAskerbefore renewal,oncetransactions inwho owns whatkeep or drop?No credentials to any of these services, ever. The only output is a question.
Fig 1. One input, three pieces, and a hard boundary. The system reads a transaction feed and sends questions; it never holds a login to anything it is auditing.

What you set up once (the outside)

  • A transaction feed. Whatever you already have: a monthly CSV export from the bank, a card provider that emails statements, or an Open Banking feed if you have one. Covered in Part 2. It needs the date, the amount, the merchant string and the card, and nothing else.
  • An owner tab. Starts empty. As subscriptions are found, somebody writes down who owns each one and what it is for, in a sentence. Filling this in for the first time is a couple of hours of archaeology and it is the most valuable couple of hours in the whole project.
  • A question window. How long before a renewal to ask, and how often to ask about the same subscription. Thirty days before an annual renewal is the useful default; monthly subscriptions get asked about once a year rather than twelve times, which is the single most important setting in the system.

What runs on every feed (the inside)

  • The grouper. Reads the transactions and finds the ones that repeat. This is harder than it sounds: merchant strings vary between charges, amounts change with seat counts and currency, and intervals drift by days. Part 3 is entirely about this.
  • The attributor. Attaches three things to each subscription: an owner, a purpose, and the true annual cost. The annual cost is the number that changes minds — “£14 a month” and “£168 a year” are the same fact and produce different decisions.
  • The asker. Sends one message to the owner before a renewal, with the annual figure, what they said last time, and three buttons. It asks once per subscription per year, which is what makes it survivable. A system that asks about eleven subscriptions every month gets filtered to a folder in six weeks.

One subscription, end to end

One subscription from first charge to renewal question, in five stagesA horizontal row of five boxes joined by arrows. Charged: fourteen pounds to some merchant. Grouped: the same charge has been seen eleven times. Named: worked out to be an actual product. Owned: attached to a person and a purpose. Asked: a question sent thirty days before the renewal. A note says the third and fourth stages are where a line on a statement becomes a decision.ONE SUBSCRIPTION, END TO ENDCharged£14, a merchantGroupedseen it 11 timesNamedwhat it actually isOwneda person and a purposeAsked30 days before renewalThe third and fourth stages are where a line on a statement becomes a decision.
Fig 2. The same system as one line. The transition that matters is from a charge to a named thing with an owner — everything before that is bookkeeping and everything after is a decision.

In plain words

There is a £14.40 charge on the company card every month from “SP * PROJTOOL”. Ten months of them. Nobody at the company can tell you what it is from the statement line, and nobody has ever had a reason to try, because £14.40 is beneath the threshold at which anybody investigates anything. The grouper spots the repetition, the attributor works out from the merchant string and a lookup that it is a project management tool, and finds no owner for it in the tab. So it asks the person whose card it is: “£14.40/month, £172.80 a year, going to PROJTOOL since September. Who owns this and what is it for?”

The answer, roughly forty per cent of the time in the first pass, is “I have no idea, I think that was for the website rebuild”. The rebuild finished in February. That is £172.80 a year that stops, and it stopped because somebody was asked a question about a named thing with an annual figure attached, rather than shown a statement line. There are usually between six and fifteen of these in a business that has been running five years, and finding them all in the first month is what pays for the project roughly two hundred times over.

Design rules that shaped every decision

  • It holds no credentials. Not to the bank beyond a read-only feed, and to none of the services it audits. It cannot cancel and will never be able to.
  • Ask once a year, not once a month. A system that asks eleven questions a month gets filtered, and a filtered system finds nothing.
  • Always state the annual figure. Fourteen pounds a month and a hundred and sixty-eight pounds a year are the same fact and produce different decisions.
  • An unowned subscription is a finding, not an error. It is usually the most valuable output of the entire system.
  • Group on behaviour, not on merchant name. Merchant strings are inconsistent and amounts change; the pattern is the interval.
  • “Keep” is a first-class answer and is recorded. The next question a year later says what was decided last time.

Why this shape

The usual approaches are an annual spreadsheet exercise, which happens once and then does not, or a SaaS-management platform, which wants admin credentials to your identity provider and costs more than several of the subscriptions it will find. Both fail for the same underlying reason: the work is not finding the charges, which are all right there on the statement. The work is turning a repeated charge into a named thing with an owner, and then asking that owner at the one moment in the year when the answer can change anything.

So the design does almost nothing except that. It reads a feed you already get, it does the pattern-matching nobody has time for, and it converts each pattern into exactly one well-timed question. It cannot act, which is not a limitation — it is what makes it safe to point at every card in the business.

The next four posts walk through each piece: how the feed arrives, how charges get grouped, how a subscription gets an owner, and how the renewal question works. One diagram per post, a cost breakdown, and an engineering reference at the end.

All posts