← Back to context

Comment by dperfect

4 days ago

It looks like this does make some things easier, but I'm not sure if it's actually better.

From what I can tell, any time you use this to check something like the customer's subscription state (or anything else payment-related) - either from the front end or the back end - it's going to perform an API request to Flowglad's servers. If you care about responsiveness, I'm not sure that's a good idea. Of course, you can cache that state if you need to access it frequently, but then it kind of defeats the purpose of this layer.

Stripe integration can be tricky, but if you don't want to store anything locally, you might as well just hit Stripe's APIs without the middleman. For the payment systems I've worked on, having cached state in the database is actually really nice, even if it's a bit more work. Want to do a complicated query on your customers based on payment/subscription state and a bunch of other criteria? It's just a DB query. With this, I think you'll be hoping they expose an API to query what you need and how you need it. Otherwise, you'll be stuck waiting for a thousand API requests to fetch the state of each of your customers.

Yeah this very true.

We have a plan to allow you to store more of this data on the merchant's side and still benefit from the work we've done to refine our data model, and make the SDK super usable. Even if you do hit Stripe's APIs, you will need to maintain mappings of price ids to your plans, your plans to what features you grant for each, stripe customer ids to your customer ids, etc. That's the kind of grunt work and maintenance burden we'd like to eliminate.

Plus, Stripe is explicitly designed to be a write-optimized system, and discourages[0] using them as a realtime read layer. We're super early in the journey but that's the problem we want to solve: how can we give software devs the same unified money movement + value movement experience that Shopify has availed to DTC brands for nearly 20 years?

[0] https://docs.stripe.com/rate-limits

  • > you will need to maintain mappings of price ids to your plans

    I think you're overvaluing how much work this is. For years I just created the plans in Stripe and then manually copied them over into my database. If you're small and not changing your plans often, this is fine.

    When eventually I got annoyed because I had a Stripe sandbox and my own staging environments I wanted to sync periodically, I banged out a 'sync' script in a couple hours. Could probably do it even less time with AIs these days.

    > your plans to what features you grant for each

    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.

    > stripe customer ids to your customer ids

    It's one extra column.

    Maybe you can call it 'grunt work' but how often are ya'all putting up new SaaS's?

    Even if you can somehow keep your latency to a minimum, if you have even a second of down time, my app goes down with yours. I don't like that. Right now if Stripe goes down for a bit, nothing happens to my app. It keeps chugging along. Maybe some of my customers can't pay their monthly subscriptions for a bit but they're not locked out of the app.

    This whole thing feels like a trap TBH. Feels like vendor lock-in. I am kind of locked into Stripe because it'd be a PITA to re-integrate with something else, but at least I own the data (sans credit card #s, which I don't want) and can move elsewhere if push comes to shove (well... OK, asking everyone to re-enter their card # would suck too).

    • The "storing my source of truth externally" is super fair, and something we plan to address soon by giving you the ability to store this data on your side. So you'll still get all the benefits of our data model and full stack SDK, but aren't locked in to our hosting.

      > 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