agreeahmed
What's frustrating is that right now when you use a payment provider, you get everything in a bundle: their flow of funds and their developer experience. Solving this is one of the big problems on our roadmap. Because yeah, you're absolutely right. You should be able to route payments flows dynamically based on what's best for the situation.
> I don't understand how your service can even help with this. "Features" are necessarily part of my app, I have to define what the user is purchasing.
We let you define features that you reference using slugs that you decide, and then group those features with products. So when someone subscribes to the product, they get the features you defined and associated with that product. So to see whether they can access a feature (boolean):
useBilling().checkFeatureAccess('fast_generations')
Or to see if they have enough credits to take a usage metered action:
useBilling().checkUsageBalance('fast_generations')
The problem we're trying to address is a bit broader than just storing price ids. You use your customers' payments state to derive billing state, and you use billing state to derive app behavior (what features they can access, what usage meters what balances and whether those are sufficient to continue consumption). You need this data on your backend and your frontend. So a substantial amount of most CRUD app code is just managing, transposing, and shuttling this kinda of data around between backend and frontend.
For fun I once mapped out a vanilla SaaS checkout flow and realized that it required a developer to coordinate 15 server-client boundary hops [0]. Each one is a liability that you have to maintain. And the flow as a whole is one of the most frustrating to test. If a developer came up with this flow on their own, we'd immediately say it smells. But it's the flow required by the current best-in-class vendors.
And it's not entirely the result of complexity intrinsic to the domain. Much of it is the result of decisions made over a decade ago that haven't really been revisited. At least in React-land, we've learned a lot in that time about how gracefully different patterns for state management age in a codebase. The last time the webhook-only pattern was the frontier of DX, Redux was the considered the best state management framework for React.
I haven't seen Redux in React code in a very long time, maybe 6 years. Not because Redux is terrible - in fact it represented the community's best understanding of state management at the time. But over time we realized the limitations of Redux as a framework, and engineered our way out of them with new frameworks. This process is natural and beautiful and part of what makes technology magical. In payments, this improvement loop is significantly rate limited. Because to build a truly better solution you have to commit to all of the uphill compliance and financial services work that people have very astutely pointed out in other comments.
[0] https://x.com/agreeahmed/status/1965258666892034257/photo/1
And the problem goes substantially beyond billing UI. There's all the unseen tedium that devs need to implement in order to derive proper app behavior based on their customers' billing state. Most of this work is transposing billing state (and its derivatives) and then lugging it to the client where it will be used to show upgrade buttons, gate feature access, show outstanding usage balances, etc.
For folks who just want to get set up and get going quickly and don't mind working with a payfac to do so, we feel they should have more options, especially when it comes to DX.
This thread has been eye opening for revealing how much more clearly we could be explaining the funds flow story. Thank you for your feedback!
Since we’re the payments provider (using Stripe under the hood), we’re not currently able to support “bring your own provider” unfortunately.
Re open source: the SaaS is under AGPLv3, and the rest is MIT.
Re “processor”: often when payment providers first get started they don’t fit into one of the established payment vendor categories because they need to piggyback off someone else’s infrastructure. We figured it would be better to make clear that we’re not a billing SaaS, but also providing payments processing - even if for now that’s through Stripe Connect.
Eg we are aligned with our merchants in worrying chargebacks in a way that “bring your Stripe key” billing SaaS is not, because our setup means their chargebacks are a concern for us similar to how they’re a concern for Stripe.
Pasting the full root license file below: — Flowglad is fully open source.
- ./packages: MIT
- ./playground: MIT
- ./platform: AGPLv3
Instead of having to implement all that yourself, you just read the latest billing and entitlement state for each of your customers from Flowglad:
const billing = flowglad(user.id).getBilling()
const hasFastGen = billing.checkFeatureAccess(‘fast_generations’)
When we begin our merchant of record offering, you will not be able to use it to sell human services. That’s not a Stripe regulation but has to do with the merchant of record offering and the compliance posture you need to build for that service.
With Flowglad’s hooks and server SDK, we get that data to your frontend and backend. So you can read it from us wherever you need it.
We’re focused on making the best DX for managing entitlements as possible. A lot of that comes down to details: cloning pricing models across environments, React hooks to manage your state. We want to build something you pick to build with on Day 1 - rather than something your boss tells you that you have to use.
In a perfect world money would trade hands and you’d just see what that meant for the features or value your customers could access accordingly. This is what happens in other domains of online commerce like Shopify. Shopify has webhooks but they are not the primary load bearing site of payment integration for most storefronts.
Payments webhooks were, from what I can tell in the history, a hack for side stepping gnarly problems in domain modeling and read optimization.
E.g. most web apps have some endpoint that the client calls to initiate a checkout session by calling their payment processor’s server SDK.
How many times has the following code been implemented because no payment processor ships a route handler and a React hook (pardon my React-brainedness)?
Someone has to do the work to get that checkout request from your frontend to your payment provider and then back so you can redirect. In a just world, that your processor’s SDK would handle that work. Otherwise it falls on your plate.
We’re not really trying to compete on cost. But we certainly aren’t more expensive once you include the cost of Stripe Billing.
We started with React because that’s what we knew best and the community we were most embedded in.
We have no dogmatic attachment to React. We hope to support Svelte and Vue soon. We’ll start on that once we feel that our data model and flow are sufficiently nailed down that we feel comfortable committing to porting our SDK to other frontend frameworks.
It turns out that the architectural changes that make that easier also make the tool generally easier to use for a bunch of different use cases.
In urban planning they have a name for this: the “curb cut effect”, whereby urban planners found that curb cuts, that had been made for a specific accessibility need such as people in wheelchairs, ended up being useful to all kinds of people: cyclists, people walking at night, pedestrians with weaker joints.
Devtools seem to benefit from a similar curb cut effect, where gains in a tool’s usability for one domain generalizes across many others.
And then we, alongside the processing partners we use on the backend (currently Stripe, soon hopefully beyond) handle the rest.
Re the sweater: great minds ;)
Eventually we want to get to a place where we are embedded deeper on the payments side. But for now that's the flow.
Doesn't exactly roll off the tongue, but that's the most precise way to describe us right now. And not necessarily where we will stay.
Issuing side (the side that "issues" the cards) is usually the one that people describe as "all of the value", while acquiring (the side that "acquires" merchants) usually is that one that needs to bring substantial volumes to market.
For context to anyone not familiar with payments, about 60-70% of the card revenue in a transaction goes to the customer's / issuing side because they are the side that assumes credit risk for the consumer. The merchant's / acquiring side has significantly tighter margins and usually needs substantial volume before it can become an interesting business. One way that entrants on the merchant side of the stack monetize is by bundling value-add software.
E.g. Stripe does this with Billing (+.7%) and Connect (+.25%).
Fwiw I agree that most people will find this tech extremely un-fun. But I'm a "payments rail guy" in the way that others might be "train guys". My inner child lights up at the thought of payment rails. My Substack, Vivid Leaves, is basically a bunch of essays about historical payment systems - some we worked with in Kenya, and others I studied from the USSR. I wrote all this before I had any idea I'd be starting a payments company: https://agree.substack.com
We know it's going to be a schlep, and we're going to have a blast schlepping through it.
* vocab fyis for anyone reading this not familiar with payments.
Imo you can trace a lot of how devtools, particularly webdev tools, have evolved to this. They are more React-brained. Specifically they try to take state management responsibilities off their users' plates.