← All posts

2026-04-18

Pricing on two axes: email and SMS bill independently

When we drafted the SMS launch, the obvious thing was to bolt SMS onto our existing email plans: bump the prices a bit, throw in some SMS credits per tier, ship. We did the math and walked away.

The cost shapes are different

Email is mostly storage and search. The marginal cost of one more message in an inbox is essentially zero — you're paying for the S3 bytes and the index entry. The Free → Dev → Team ladder is a ladder of limits, not volume.

SMS is mostly per-message. The carrier charges for every send. The Free → Pro → Business ladder is a ladder of credits-included, with overage priced at the credit-pack rate. Conflating the two forces customers to overpay for one axis to get the other.

What we shipped

Two independent plan dimensions on the tenant. Email plan governs inbox count, retention, daily inbound cap. SMS plan governs monthly SMS grant, voice minutes, dedicated phone numbers.

tenant.plan      = 'free' | 'dev' | 'team' | 'scale' | 'enterprise'
tenant.sms_plan  = 'free' | 'pro' | 'business' | 'enterprise'

On the pricing page, those are two grids. You can be on email=Free and sms_plan=Pro, or vice versa. The Stripe webhooks for each axis are independent — paying for SMS Pro doesn't silently bump your email plan.

Hidden cost: the credit-pack honesty problem

We expose pay-as-you-go credit packs alongside the SMS plans. The cheapest pack rate ($0.05/credit) is the "true" marginal cost we pass through. The plan grants effectively buy in bulk: Pro gives you 1,000 SMS/mo for $29 (versus $50 if you bought them as packs). Business gives you 5,000 for $99 (versus $250).

We could hide this and run plan grants at a higher implied price. We don't. The pricing page shows the credit-pack rate next to the plans; the usage dashboard estimates overage cost using the cheapest pack rate. If you'd save money on a higher plan, you should switch. We'd rather lose a few dollars per customer than have you discover the math at renewal time and resent us for it.