Somewhere in our billing flow, a single, well-intentioned .title() call decided to make things look nice. It did not break the build. It did not throw an error. It did something far more sinister: it returned 400 Bad Request to paying customers trying to upgrade, and it took us a while to figure out why.

The cast of characters

We have three plan tokens that travel end-to-end — frontend → createBillingCheckout → backend BillingCheckoutRequest:

  • core
  • growth
  • core_sla

They are lowercase. They are meant to stay lowercase. They are, in essence, identifiers — not prose.

The crime

Somewhere, someone (it’s always someone) ran the plan token through title-casing to make it presentable in a label, and that “presentable” value leaked into the value sent to the backend:

"core_sla".replace(/_/g, " ")   // "core sla"
// ...title-cased for display...  // "Core Sla"

Watch what happens to our carefully distinct tokens:

OriginalAfter “make it pretty”Backend sees
coreCorecore ✅ (lucky)
growthGrowthgrowth ✅ (lucky)
core_slaCore Slanot a valid token

The single most important plan — core_sla, the one with the SLA guarantee, the premium tier, the one that makes money — got mangled. Its distinguishing _sla suffix collapsed in the cosmetic wash, and the self-serve upgrade guard rejected it with a 400. Customers who wanted to give us more money were told, essentially, “no thank you, that plan doesn’t exist.”

Core and core_sla looked similar enough to a human and identical enough after title-casing to become indistinguishable. Capitalization, it turns out, is not a free aesthetic upgrade when the string is load-bearing.

The fix

Keep identifiers as identifiers, all the way down:

// the token stays lowercase, end to end
const planToken = "core_sla";          // never .title(), never prettified in transit
createBillingCheckout({ plan: planToken });

If you want a pretty label for the UI, derive it separately and never send the pretty version back to the server:

const LABELS = { core: "Core", growth: "Growth", core_sla: "Core + SLA" };
// display LABELS[planToken]; transmit planToken

It’s now a documented house rule: billing plan tokens stay lowercase end-to-end.

The moral

  • Display strings and identifiers are different species. The moment you let a display transform touch a value that gets compared, looked up, or validated, you’ve planted a bug with a delay fuse.
  • Lossy transforms (.title(), .toLowerCase() on the wrong thing, trimming, slug-ifying) are especially dangerous on near-identical keys, because the failure only shows up on the one key that loses information.
  • The scariest bugs don’t crash. They return a confident 400 and let you assume the customer did something wrong.

A capital C nearly cost us our best-margin plan. Respect your strings. Some of them have jobs.


Amit Jethva is the CTO and co-founder of Nuvika Technologies Pvt Ltd, makers of Fintropy, a multi-cloud FinOps platform. Learn more at nuvikatech.com.