The procurement director at a mid-sized manufacturer called me on a Tuesday in March. Eleven months earlier her team had shipped an order-tracking application in six weeks — no developers, three business analysts, one very opinionated operations lead. She was proud of it, and she had earned that pride.
Then finance sent her a number.
"Our headcount has not changed," she said. "We added nine users in a year. So explain to me why this system costs four times what it did in January."
I did not have an answer ready. That is the part I still think about.
Not because the numbers were wrong. Because I could not tell her which part of her system was expensive. I could show her seat count. I could show her storage. Neither explained the curve. Somewhere in that application something was spending money on her behalf, thousands of times a day, and my platform had no way to name it.
Low-code moves cost from people to runtime
Every low-code platform sells the same promise: fewer people, less time, less money. And for the build phase, that promise mostly holds. What we do not say out loud is that we did not remove the cost. We moved it.
In a hand-written system, cost lives in salaries and in infrastructure you can roughly size in advance. In a low-code system, a business analyst can create runtime work with a drag. A validation rule on a table is a function that runs on every save. An automation that fires on record update is a queue consumer. A scheduled job that recalculates a summary is a batch process. A workflow that starts on import is a fan-out.
None of that looks like software. All of it is software, and all of it is metered somewhere, whether or not you kept the meter.
The industry default is to price seats, because that is what SaaS taught us. Seats are easy to count and easy to explain. But seats are a proxy for value, not for consumption. The moment your platform gives a non-engineer the power to create execution, seats stop predicting cost. You have sold thirty licences and you are paying for four hundred thousand script runs.
The meter is an architecture problem, not a billing feature
Here is the mistake I made, and I think most platform teams make it in the same order. We treated metering as a billing concern — something the finance integration would handle later, after the product was good. Add a counter, multiply by a rate, send it to Stripe.
That is not metering. That is arithmetic on data you do not have.
To meter execution you need attribution. When a script runs, you must be able to answer: which application, which tenant, which table, which user or system actor, which trigger, which version of the configuration. When an automation fans out into twelve sub-steps and three of them call an AI model, the consumption of those sub-steps must still resolve back to the record that started it. When a scheduled job wakes up at 2 a.m. and touches forty thousand rows, "the platform did it" is not an answer a customer will accept on an invoice.
We did not have any of that, because we had built execution isolation and we had never built execution identity.
And here is the uncomfortable discovery: the exact information that makes a system billable is the information that makes it debuggable. The customer asking "why did my bill quadruple" and the support engineer asking "why did this record take nine seconds to save" are asking the same question with different vocabulary. Both need the same thread of attribution through the same hops.
If you cannot explain the cost, you cannot explain the behaviour. If you cannot explain the behaviour, you do not have an enterprise product. You have a demo that happens to be in production.
What we ended up building
Three things, and none of them were glamorous.
First, an execution context. Every entry point — a form save, an API call, an automation trigger, a scheduled task, an AI agent invocation — opens a context, and that context propagates through every synchronous hop and every queued hop. It carries the tenant, the application, the actor, the trigger, and a correlation identifier. This is the same plumbing you need for tracing, which is why we stopped pretending it was two projects.
Second, a ledger. Not a counter. A counter gets reset, drifts, and cannot be reconciled. A ledger records the delta and the balance after the delta, with the reason attached. It is append-only. When the finance team asks why February differs from January, you can point at the specific automation that changed behaviour, not at a number that grew.
Third, attribution surfaced in the product. The expensive thing about a meter is not the measurement; it is the conversation. Once we could attribute consumption, we could tell a builder that the validation rule they wrote fires four hundred thousand times a month. That single sentence changed more customer designs than any performance documentation we ever wrote.
Quotas are guardrails, not punishments
There is a design trap here. Once you can measure, it is tempting to make the meter a weapon: hard caps, sudden failures, an upsell email triggered by the first overage. We tried some of that. It produces a specific kind of customer, the one who is afraid of their own platform.
The better pattern is the one physical systems use. A soft limit that warns while it is still cheap to act, a hard limit that degrades the right thing and protects the important thing, and a clear statement of what a unit actually is. Customers forgive a quota they understood. They do not forgive a silent failure in a production approval chain because a background recalculation ate the month.
This is also why we publish the dimensions we meter honestly — users, applications, tables per application, rows per table, file storage, and a monthly allowance of AI credits — rather than hiding them behind a sales conversation. A customer can disagree with your pricing. A customer cannot plan around a number you will not state.
Retries deserve their own sentence, because they are where naive meters lie. Most of our early double-counts came from retry logic, async redelivery, and fan-out. Consumption has to be attributed at the point of actual work, not at the point of intent. If a job is attempted three times and one attempt succeeds, the honest number is not three, and it is definitely not one.
The uncomfortable conclusion
We thought we were building an application builder. We were building a metering and governance system, and the builder was the easy half.
The features that make a low-code platform feel magical — drag, generate, automate, connect — are precisely the features that spend money without asking permission. That is their value and their danger, and it is the same property. You cannot keep the magic and skip the meter.
So if you are early in this build, do the unglamorous thing first. Give every execution an identity. Write it down. And be ready, on a Tuesday in March, to tell a proud customer exactly which of their ideas is expensive.
Because the bill always arrives.
The only question is whether you can explain it.
Top comments (1)
publishing the dimensions is the right call, but i don't think it's enough on its own. a finance person can read "rows per table" and still not predict next month's bill until they've watched a month of runs. a per-automation cost estimate at save time would catch more of the surprise than a pricing page ever will.