Skip to main content
BlogUncategorized

Per-User AI Limits: Making a Personal App Multi-User

By August 5, 2026No Comments

Pulso, my watch collection app, had an AI budget that any one user could spend on behalf of everyone else. I found it on 30 July while wiring up the chat advisor, and fixing it turned into the actual work of the week: making an app I built for exactly one person safe for a second one.

The bug was easy to state and easy to miss. The usage table counted model calls for the app rather than for the person making them. One user asking a lot of questions would quietly exhaust the monthly allowance for everybody, and the next person would just see an advisor that had stopped answering, with nothing in the interface explaining why. Usage is now keyed by user_id, so an allowance belongs to a person rather than to a deployment.

A single-user schema is a decision you make by accident. Everything else came from the same root. Pulso’s Postgres tables assumed one collection because, for months, there was one. Watches, shortlist, wear logs, stories, service records, prices, shares: seven tables, none carrying a user_id, all readable by anything holding a key. That is fine right up to the moment it is a data leak. Every one of those tables now has a user_id and row-level security on top, so the database itself refuses to hand over someone else’s collection even when the application layer asks politely. I would rather a wrong query return nothing than trust myself to always write the right one.

Cost should be visible before it is spent. The advisor can run a paid lookup that takes around 45 seconds and costs real money. It now says so before it fires, stating the cost and the wait and then waiting for a yes. Underneath that, three of the most common questions (what the collection is worth, what shape the shortlist is in, what is sitting below my target price) are answered locally with no model call at all. The cheapest AI call is the one you worked out you never needed, and an advisor that spends your money to tell you something it could have counted is not an advisor, it is a meter.

Shipping it is what found the real bugs. Asking about a watch I already own spent a paid lookup and came back with nothing, because the question was never matched against my own collection first. A clarifying question from the model rendered as a failure with no way to reply to it, so the honest answer looked like a broken one; it now has an "Answer that" action. Price search failed on real watches when the suggestion model invented a reference number, and now retries on brand and model alone. None of those show up in a demo. They show up the first time you use the thing in earnest.

The most embarrassing one was infrastructure. The advisor backend had never actually been deployed. Three commits sat unpushed while I tested happily against localhost, and in production /api/suggest and /api/usage returned 404 to an app that was confidently calling both. It worked on my machine, which is the oldest sentence in software and still the truest.

What is not solved: Pulso still has exactly one real user, me. The schema now assumes more, the allowance now assumes more, and none of it has been proven against a second account under real use. I am claiming the shape is right, not that the multi-user experience is.

Leave a Reply