Mesrai
Back to blog
// essayTechnical Deep Dive

A One-Character Bug in a Pricing Tier Check: The $X-Per-Month Save

Real incident: `<` instead of `<=` in tier check — $24K leaked over 3 months. Boundary-test fix.

Mesrai TeamSeptember 3, 20268 min read

Real incident: a one-character bug in the pricing-tier comparison let paid-plan users hit free-tier limits but get charged free-tier rates. ~$8K/month revenue leak for 3 months until reconciliation flagged.

The vulnerable diff

tsbilling/tier-check.ts
// billing/tier-check.ts (the buggy check)
const TIERS = [
  { name: "free", limit: 10_000, monthlyRupees: 0 },
  { name: "pro",  limit: 100_000, monthlyRupees: 999 },
  { name: "ent",  limit: Infinity, monthlyRupees: 9999 },
];

function billingTier(usage: number) {
  for (const tier of TIERS) {
    // BUG: < instead of <=. usage exactly at boundary falls through wrong.
    if (usage < tier.limit) return tier;
  }
  return TIERS.at(-1)!;
}

What is wrong

Tier-boundary math is a place where one wrong character is expensive. `usage < tier.limit` excludes the boundary value; `usage <= tier.limit` includes it. The right choice depends on whether the limit is inclusive (you may USE 10K but no more) or exclusive (you may USE up to 9,999). Documentation said inclusive; code said exclusive. The mismatch let some customers fall into the lower tier when they should be in the higher one.

The attack

Discovery:

textexploit
3 months after the regression:
- Finance reconciles: revenue lower than expected by ~$8K/month.
- Investigation: tier distribution doesn't match plan-purchase ledger.
- 142 customers purchased pro plan, billed as free.
- 142 × $11.99/month × 3 months = ~$5,100 leaked just from this segment.
- More from a similar enterprise-tier confusion: ~$3K/month.

Cumulative: ~$24K leaked over 3 months. Recoverable via re-bill but
customer-relations cost is the bigger problem.

Off-by-one in commerce code is expensive.

Mesrai's review comment

textreview-comment.txt
mesraipilot · Bot · reviewed 30 sec ago

[mesrai] [code-review] [Logic] [Off-By-One] [high]

`usage < tier.limit` excludes the boundary value. Confirm the
inclusive/exclusive semantics with product/billing.

If limits are inclusive ("up to 10K"):

  if (usage <= tier.limit) return tier;

If limits are exclusive ("less than 10K"):

  if (usage < tier.limit) return tier;
  // Adjust limits accordingly: free = 9_999, pro = 99_999, etc.

Add a property-based test that covers exact boundary values:

  test("billingTier at exact boundaries", () => {
    expect(billingTier(0)).toBe("free");
    expect(billingTier(10_000)).toBe("free");   // if inclusive
    expect(billingTier(10_001)).toBe("pro");
    expect(billingTier(100_000)).toBe("pro");
    expect(billingTier(100_001)).toBe("ent");
  });

The fix

tsbilling/tier-check.ts + tests (fixed)
// billing/tier-check.ts — fixed
function billingTier(usage: number) {
  for (const tier of TIERS) {
    if (usage <= tier.limit) return tier;   // inclusive (matches docs)
  }
  return TIERS.at(-1)!;
}

// tests/tier-boundary.test.ts
test("billingTier exact boundaries", () => {
  expect(billingTier(0).name).toBe("free");
  expect(billingTier(10_000).name).toBe("free");
  expect(billingTier(10_001).name).toBe("pro");
  expect(billingTier(100_000).name).toBe("pro");
  expect(billingTier(100_001).name).toBe("ent");
});

Comparison matches the documented semantics. Boundary tests prevent regression.

Why human review missed it

Off-by-one bugs in commerce code are catastrophic in aggregate. Mesrai catches comparisons against tier limits without paired boundary tests.

Related rules + further reading

Mesrai rule pack: logic/tier-comparison-boundary — flags tier-limit comparisons without exact-boundary tests.

Property-based testing libraries (fast-check) excel at this class.

Real-incident class in SaaS billing.

Takeaway

One character. Tier check off-by-one. Revenue leak. Mesrai catches the missing boundary tests.

// try

See it on your next PR.

Free for individuals. Install in two minutes. Mesrai reviews every commit.