Credits stop working the moment two actions are 12x apart in cost
Credits look like a solution to variable cost. They're really a way of moving the variance onto the user without telling them.
In Arteza a quick edit and a full multi shot render are about 12x apart in what they cost us to run. Both are priced in the same unit. So someone learns an exchange rate from the cheap action, builds a mental model, then spends a third of their balance in one click and feels robbed. That isn't a pricing bug. We asked them to hold a cost model in their head that we never showed them.
What's worked is putting the credit cost on the button before the click instead of in a docs table. Boring fix, and it cut the where did my credits go messages more than any price change we made.
The part I haven't solved is failures. A bad output still burned the compute. Refund it and people retry until they like the result. Don't refund and credits feel like a slot machine. We refund and eat it, which won't scale.
Curious where others have landed on charging for output the user rejects.
Replies
That slot machine feeling is so real when users burn credits on bad outputs. I've seen a few teams use a free retry token for failed jobs instead of touching credit balances. How are you detecting system failures vs bad prompts on your end?
@faysal_fateh Badly, is the honest answer. The clean cases we catch, a timeout, a safety block, a model returning nothing, and those refund automatically with no human in it. The messy middle is a render that completed fine and just isn't what they pictured, and nothing we log separates that from a weak prompt. A free retry token is interesting precisely because it skips the classification, we'd just cap it and move on.
Dial
the binary refund/no-refund framing might be the actual trap here, not just the exchange rate problem. what if failures split into a small flat "attempt fee" that's non-refundable no matter what (covers your infra overhead on every call, priced low enough nobody notices) plus the real compute cost only charged on an accepted output? that way a bad multi-shot render costs the user roughly what a bad quick edit costs them, and the expensive part of your margin only gets collected when you actually delivered something they wanted. doesn't fully solve the "retry until happy" abuse case, but it stops a single failed 12x action from feeling like getting robbed, which sounds like the actual trust problem you're describing.
@galdayan The attempt fee is the first version of this I could actually ship, because it charges for the part that's genuinely fixed and leaves compute on the outcome. What worries me is that accepted turns into a button somebody has to press, and once approval is a step, most people skip it and I've built a collections problem instead of a pricing one. It might work if acceptance is implicit, they downloaded it or fed it into the next step. Going to try that on edits first, they're cheap enough to be wrong about.
Dial
@asadmalik901 an explicit accept button just moves the friction, it doesn't remove it, like you said. a time-based implicit signal might get you further on edits specifically - if they don't hit undo or regenerate within some short window, count it as accepted. still noisy for something like code where a bug shows up days later, but edits are fast enough to actually judge that way
@galdayan A time window is the version I can build without shipping new UI, so that's probably where I start. The catch is our renders take about 40 seconds, so a short window is mostly the user still waiting for the thing to finish. I'd have to start the clock when the result lands, not when the job does. Regenerate is the honest signal anyway, nobody regenerates something they were happy with.
Dial
@asadmalik901 makes sense, clock-from-result-not-job is the fix that actually matches how people use the thing. curious if you'll end up needing two different windows though, one for edits and a longer one for something like code where the bug shows up days later like you said - or is that second case just out of scope for this fix
Softorino 💻📲
I market a file converter where a voice memo and a 2 hour video are both one conversion in the UI and nothing alike underneath, so the exchange rate problem is familiar. On failures, most of the ones I see turn out to be the file being wrong rather than the service breaking, which makes charging feel unfair either way. How would you tell someone an attempt is going to fail before they spend anything on it?
@yelyzaveta_kibets A cheap pre-check on the input before the expensive path runs. For us that's resolution, duration and whether the reference image is actually what they said it was, and it catches maybe half. The rest only fails after the compute is spent, so we stopped trying to predict those and made them free instead. Your case is kinder than mine, a voice memo and a 2 hour video are separable from the header alone.
The upfront cost solve the surprise, but failed still create a trust gap. Could a small retry allowance help balance user frustration with your compute costs?
@jeankang Probably, and the number matters more than the idea. One free retry per generation reads as fair, three reads as an invitation to reroll until the slot machine pays out. I'd also make it per generation rather than a monthly pool, because pools get hoarded and then argued about at renewal.
@galdayan Fair, and abandoned one step later is a real hole. What makes me okay with it for now is that the drag is deliberate and the abandon isn't, so I'm charging for intent, which is at least a line I can defend to someone asking for a refund. If the abandon rate after a drag turns out high I'll move the signal again, but I'd rather be wrong on a handful of outputs than ship an approval queue.
Dial
@asadmalik901 charging for intent instead of outcome is a defensible line, but it's still a proxy, same as the score-vs-linter thing floating around this forum right now - drag is the visible signal, it's not the thing you actually care about, which is whether they got value. the interesting number isn't the abandon rate after a drag, it's whether people who drag-then-abandon come back later and use that same output anyway once they've cooled off. if that's non-trivial, you're not undercharging walk-aways, you're charging some of them twice in spirit, just spread across two sessions instead of one.
@galdayan I don't have that number, and not being able to pull it is the more useful finding. Our events don't link a later session back to an output from an earlier one, so someone coming back cooled off looks identical to a fresh view. That's the same missing lineage id that bit me on the model logging thing, different table. I'd rather add it than keep tuning a rule I can't measure.