Running our own inference stack as a small company
Renting a hosted model would have been faster and, at our volume, probably cheaper. We chose the harder path because the alternative meant handing every conversation to a company whose business depends on knowing things about people.
The decision
The default for a small team is obvious: call somebody else’s API, ship in a week, worry about it later. The problem is that "later" never comes with leverage. Once your product depends on a provider, their retention policy is your retention policy, their terms of service are your privacy promise, and any change they make lands on your users without your consent.
So we operate the stack ourselves. We deploy the model, tune the serving layer, own the hardware budget, and answer for every byte that touches it. That is a real cost, and it shows up in three places: capacity, latency and the number of hours two people can spend on infrastructure instead of product.
Capacity planning without a hyperscaler
Hosted providers hide the awkward truth that inference capacity is lumpy. A model either fits on the accelerator you have or it does not, and the gap between "comfortable" and "queueing" is much narrower than a dashboard suggests. Our planning is deliberately conservative:
The rule we will not break: there is no cloud fallback. If our capacity runs out, the answer is a wait or an apology — never a quiet hop to a third party.
Cost per answer
Owning hardware turns a variable cost into a fixed one, which is uncomfortable early and pleasant later. Below a certain volume we are paying for silicon that idles. Above it, every additional answer is nearly free, and our margin stops being a function of somebody else’s price list.
That shape is why the pricing is what it is. Free tiers are limited not to upsell you but because a free request costs us real electricity on a machine we bought. We would rather be transparent about that than pretend it is magic.
What it cost us
Debuggability, mostly. A managed provider gives you dashboards, traces and someone to page. We gave that up, and we also chose not to keep the transcripts that would make debugging easiest. Diagnosing a bad answer with a thirty-day excerpt and a latency number is slower than reading the full conversation — and that is the trade we accept in exchange for having nothing worth stealing.
What is next
Better batching for long-running Flows, so a background job cannot starve a person waiting on a chat turn, and a clearer capacity signal in the app. We will publish the numbers once they are stable enough to be worth publishing.