# The Capital Letter That Broke Billing

_How `Core` quietly ate `core_sla` and charged the wrong plan._

June 16, 2026 · 3 min · Amit Jethva

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:

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

Watch what happens to our carefully distinct tokens:

| Original  | After "make it pretty" | Backend sees |
|-----------|------------------------|--------------|
| `core`    | `Core`                 | `core` ✅ (lucky) |
| `growth`  | `Growth`               | `growth` ✅ (lucky) |
| `core_sla`| `Core Sla`             | ❌ **not 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:

```js
// 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:

```js
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](https://www.nuvikatech.com/Fintropy_Overview.html), a multi-cloud FinOps platform. Learn more at [nuvikatech.com](https://www.nuvikatech.com)._
