DEV Community

KunStudio
KunStudio

Posted on • Originally published at overlap-audit.pages.dev

Detecting redundant subscriptions by category instead of matching names (all client-side, localStorage only)

Detecting redundant subscriptions by category instead of matching names (all client-side, localStorage only)

Plenty of subscription trackers will list what you're paying for. The harder, more useful question is which of those tools are doing the same job as each other — and which one to keep. Overlap Audit answers that by grouping entries by category rather than trying to pattern-match service names, and it runs entirely against localStorage, with no backend involved.

Normalizing before comparing

You can't compare a $120/year tool to a $12/month tool directly — one of them has to be converted first. normMonthly(price, billing) divides annual prices by 12 before anything else happens, so every downstream calculation (totals, overlap waste, cost-per-use) works off one consistent monthly figure regardless of how the user actually gets billed.

Overlap is a category problem, not a name problem

The obvious approach — string-matching service names to find duplicates — falls apart immediately, because the real overlap in most people's subscription list isn't two services with similar names, it's two or three services doing the same job under completely different names (two cloud-storage tools, two AI writing tools, three streaming services). So the tool groups entries by a user-assigned category instead: for any category with two or more entries, it sorts by normalized monthly cost, keeps the cheapest as the one worth having, and flags the rest as redundant — summing their cost as the waste attributable to that overlap.

A second, unrelated waste signal

Overlap isn't the only way a subscription is a bad deal. A tool can be perfectly non-redundant and still be a waste if nobody's using it: the audit separately flags anything with zero recorded uses this period, or a cost-per-use at or above a fixed threshold. Those two waste sources (redundant-with-something-else, and low-value-on-its-own) are computed independently, then de-duplicated before being added to a total potential-savings figure — an item already counted as redundant doesn't also get counted again under the low-value bucket, or the headline savings number would overstate what cancelling everything flagged would actually save.

One thing to cut, not a wall of flags

A results page that flags six problems and asks the user to prioritize them is asking the user to do the analysis the tool was supposed to do. So on top of the category breakdown, there's a single "cut this first" callout: whichever flagged item has the highest waste amount, with a one-line reason (duplicates a cheaper tool in the same category / unused this period / costs a lot per use) and the annualized number cancelling just that one item would save. One concrete next action beats a complete list every time the goal is to get someone to actually act on it.

No backend, on purpose

Every row lives in localStorage as a small JSON blob ({rows, currency}), reloaded on page load and rewritten on every edit. First-time visitors see a small set of example rows so the layout and the overlap logic are visible before anyone types in real numbers, and editing any seeded row quietly converts the whole set from example data to the user's own — no separate "start fresh" step required. There's no reason this particular tool needs a server: nothing here has to be shared across devices or persisted past the browser it was entered in, and skipping the backend means skipping an entire class of problems that comes with it.

Live tool: https://overlap-audit.pages.dev/?utm_source=devto&utm_medium=backlink

Happy to go deeper on the overlap-grouping logic or the localStorage/demo-seeding pattern if useful — drop a comment.

Top comments (0)