Home/ Blog/ Article

Transaction categorisation in personal finance apps: build, buy, or blend

ยท

A personal finance app’s core promise is simple: show someone where their money goes without them doing the work themselves. Underneath that promise sits one of the least glamorous, most consequential engineering decisions in the product: how a raw bank transaction string turns into a category a person actually recognises. Get this wrong and the app becomes another spreadsheet nobody trusts. Get it right and it’s the feature that makes the rest of the product worth having.

We built this into Money Master AI, our own personal finance product, so the trade-offs below come from doing the work rather than reading about it. The decision of whether to build categorisation in-house, buy it from a vendor, or blend the two is one every team working with transaction data has to make early, because it shapes the data model, the budget, and how much ongoing engineering attention the feature demands for as long as the product exists.

What categorisation actually involves

It’s tempting to think of categorisation as matching a merchant name to a label. In practice it’s several separate problems stacked on top of each other, and most of the engineering effort goes into the parts nobody mentions in the pitch deck.

  • Merchant name normalisation. The descriptor a bank sends is rarely a clean merchant name. It’s a truncated string with reference numbers, POS terminal IDs and inconsistent formatting that varies bank to bank.
  • Category assignment. Deciding whether a normalised merchant belongs to groceries, dining, subscriptions or something else, including merchants that legitimately span categories.
  • Recurring transaction detection. Spotting subscriptions and standing orders reliably enough that a user trusts the app to flag them, not just list them.
  • Cross-border and multi-currency transactions. Foreign merchant strings, currency conversion, and descriptors that don’t map to any UK-centric merchant dictionary.
  • Split or ambiguous transactions. A supermarket that also sells fuel, a pharmacy that also sells groceries, a marketplace platform that could be almost anything.

None of these are solved once. Each one needs a maintenance plan, because merchants change their descriptors, banks change their formats, and new merchants appear every week.

Three ways to build it

Rule-based matching

The cheapest way to start. A dictionary of known merchant strings mapped to categories, with pattern matching for the rest. It works well for common, high-volume domestic merchants and falls over quickly on the long tail: independent shops, foreign merchants, anything with a variable reference number embedded in the string. Rules need continuous upkeep, and the person maintaining them becomes a permanent, unglamorous line item on the roadmap.

In-house machine learning

A classifier trained on labelled transaction data can generalise to merchants a rules engine has never seen, and it improves as users correct miscategorised transactions. The catch is that it needs volume and labelled data to be worth building at all. On day one you have neither. It also introduces an MLOps commitment most small teams underestimate: monitoring for drift as spending patterns and merchant strings shift, retraining on a schedule, and instrumenting the correction loop so user feedback actually improves the model rather than sitting in a table nobody reads. This route earns its cost when categorisation accuracy is a genuine differentiator for the product and there’s a realistic path to enough active users generating corrections to train on.

Third-party enrichment API

Several providers now sit on top of Open Banking connections and return enriched, categorised transaction data directly. Integration is fast and gives a reasonable quality baseline from day one, without a training data problem to solve first. The trade-offs are a recurring per-transaction cost that scales with usage, a category taxonomy you don’t fully control, dependence on the provider’s coverage of UK banks and merchants, and a new vendor in the data supply chain whose reliability and pricing changes become your problem too.

Most working products end up blending approaches: an enrichment API or a rules engine for the baseline, with a thin in-house layer for corrections, merchant overrides, and anything specific to the product’s own category taxonomy. Pure in-house machine learning from a standing start is rarely the right first move.

Where it breaks in production

Categorisation quality that looks solid in a demo tends to degrade in ways that only show up once real users bring real accounts. New and unfamiliar merchants appear continuously, and every one that lands in the wrong category, or worse in no category, chips away at trust fast. Users disagree with categories for legitimate reasons of their own, which means a correction interface isn’t a nice-to-have, it’s part of the core mechanism, and those corrections need to feed back into whatever is doing the categorising or the same mistakes repeat indefinitely. Foreign transactions and split-purpose merchants generate a disproportionate share of support queries relative to their volume. And banks change transaction descriptor formats without notice, which means anything hard-coded against a specific string format will silently degrade until someone notices the pattern in support tickets.

Data protection is not optional

Transaction data is unusually revealing. Income, spending on health, debt repayments, relationship changes and much else can be inferred from a transaction history, which makes it some of the most sensitive personal data a consumer product can hold. Under UK GDPR that means data minimisation, clear purpose limitation, defined retention periods, and encryption both at rest and in transit as a baseline, not an afterthought bolted on before launch.

If enrichment or categorisation is outsourced to a third party, that vendor becomes a processor handling some of the most sensitive data in the product, which means proper due diligence on their security posture, clarity on where the data is actually processed and stored, and a data processing agreement that reflects the real data flow rather than a generic template. If the product connects to Open Banking directly rather than through a regulated intermediary, that also brings FCA authorisation requirements into scope, which is a separate and non-trivial decision in its own right.

How to decide

Before committing engineering time to one approach, it’s worth working through these questions honestly rather than defaulting to whichever option looks most impressive in a pitch.

  • Is categorisation accuracy the actual product differentiator, or a supporting feature users expect to just work?
  • Do you have, or can you realistically get, enough labelled or user-corrected transaction data to train and maintain a model?
  • Does the team have the ongoing capacity for MLOps, or would that capacity be better spent elsewhere in the product?
  • Does a recurring per-transaction fee work at your expected volume and pricing model, both now and at scale?
  • Are there data residency or regulatory constraints that rule out certain vendors or processing locations?
  • Is there a correction feedback loop in the design from day one, regardless of which approach is chosen underneath it?
  • How much time to market pressure is there, and does building a baseline in-house actually delay the parts of the product that matter more?

For most teams starting out, buying a baseline and building the correction and override layer on top gets a trustworthy product in front of users faster than building categorisation from scratch. In-house machine learning becomes worth the investment once categorisation itself is the thing users are paying for, and there’s enough real usage to keep a model honest. The mistake to avoid is treating the choice as permanent: the data model and the correction pipeline are worth designing so the underlying categorisation engine can be swapped later without a rebuild.

Filed under: