Skip to content

Built the payments and entitlements layer — Stripe alongside Apple and Google in‑app purchase — gating the directory, search and export through an 11‑table access model checked on the server.

Situation. Money is the part of a platform nobody gets to be casual about. A subscription has to survive a card expiring, a refund, a plan change, a webhook that arrives twice and a webhook that arrives out of order. The moment payment can happen on three storefronts — a card on the web, Apple in one app store, Google in the other — there are three different accounts of what somebody bought, and the product still needs one answer to one question: what is this person allowed to do right now?

Task. Taking money and granting permission had to be two systems rather than one, so that adding a storefront would not mean rewriting every gate in the product.

Action. Stripe handles cards and subscriptions through 18 Go files, and Apple and Google in‑app purchases arrive through their own receipt verification. All three converge on a payments schema of 9 tables and 34 functions — and then stop there. What the product actually asks is a separate access schema, 11 tables and 34 functions, which answers “may this account do this?” without knowing or caring which storefront paid for it. That answer gates the company directory, search and data export, and it is re‑checked on the server on every request, because a hidden button is a courtesy and not a control.

Result. Adding a storefront now touches the payments side and leaves the gates alone, and a support question about someone’s access has one table to look at rather than three. The cost is two schemas where a smaller product would want one, plus an entitlement lookup on requests that would otherwise have been free.