Best Practice for Managing Payment Subscription Tier Status

I'm trying to understand the best way to approach how to manage and update a user’s payment subscription status in a web application. Let’s say you have a subscriptions table in a database that is updated via webhooks such as with a payment service like Stripe that updates the subscription table given events like creating a subscription, canceling a subscription etc. When the user makes requests to your backend, you ideally want a quick way to check the user subscription status to see if they can create resources, limit the number of resources they create, or whether they can access certain resources in general. I have thought of a few ways you could approach this but I'm not sure what is really the ideal way or the conventional approach. You can try to attach a subscription tier status to a user’s auth session, that way the tier information is attached when handling various requests. The problem with this approach is that the user could have multiple sessions on various devices making updating this tricky. Moreover, if you store a user’s session in something like Redis, the key is likely a session value, which you would not have access to from a Stripe webhook to your backend even if it contains a user id or customer id. I suppose you could try to counter act this with adding another key value pair that has a user id that references the user’s sessions as a value but something tells me this is not ideal. Rather than attaching a subscription tier to the user’s session, you could create a second key value pair in something like Redis that holds the user’s subscription tier with a user id key and a value of a tier. This seems like the best approach though you do have a whole other key value pair in addition to the user’s session. Rather than relying either of these methods, you could query the subscriptions table on all requests that need to check the subscription tier, but I can see this getting expensive and costly if you have to query the subscription table on nearly every request that involves a check for a user’s subscription status. It just seems more ideal to be able to handle this idea in something like Redis rather than querying a main database. Even if you decide with the Redis approach, it still seems like there is a point of failure where your database could be updated but not Redis leading to a situation where these key value pairs which you are relying on to be a source of truth of subscription status are not aligned with what the subscription status actually is (which is in the database which is further abstracted from the real truth of the payment provider like Stripe). Ultimately you have in essence 3 "sources of truth", the payment service like Stripe which is the real source of truth, the database which could be out of sync if the webhooks fail enough times, and Redis which is even one more layer removed from the database. I'm just not sure about what's the best way or conventional way to handle these problems given wanting to have accurate subscription information, easy to understand logic, and also make the process efficient.

Jun 3, 2025 - 21:20
 0

I'm trying to understand the best way to approach how to manage and update a user’s payment subscription status in a web application. Let’s say you have a subscriptions table in a database that is updated via webhooks such as with a payment service like Stripe that updates the subscription table given events like creating a subscription, canceling a subscription etc. When the user makes requests to your backend, you ideally want a quick way to check the user subscription status to see if they can create resources, limit the number of resources they create, or whether they can access certain resources in general.

I have thought of a few ways you could approach this but I'm not sure what is really the ideal way or the conventional approach.

  1. You can try to attach a subscription tier status to a user’s auth session, that way the tier information is attached when handling various requests. The problem with this approach is that the user could have multiple sessions on various devices making updating this tricky. Moreover, if you store a user’s session in something like Redis, the key is likely a session value, which you would not have access to from a Stripe webhook to your backend even if it contains a user id or customer id. I suppose you could try to counter act this with adding another key value pair that has a user id that references the user’s sessions as a value but something tells me this is not ideal.
  2. Rather than attaching a subscription tier to the user’s session, you could create a second key value pair in something like Redis that holds the user’s subscription tier with a user id key and a value of a tier. This seems like the best approach though you do have a whole other key value pair in addition to the user’s session.
  3. Rather than relying either of these methods, you could query the subscriptions table on all requests that need to check the subscription tier, but I can see this getting expensive and costly if you have to query the subscription table on nearly every request that involves a check for a user’s subscription status. It just seems more ideal to be able to handle this idea in something like Redis rather than querying a main database. Even if you decide with the Redis approach, it still seems like there is a point of failure where your database could be updated but not Redis leading to a situation where these key value pairs which you are relying on to be a source of truth of subscription status are not aligned with what the subscription status actually is (which is in the database which is further abstracted from the real truth of the payment provider like Stripe). Ultimately you have in essence 3 "sources of truth", the payment service like Stripe which is the real source of truth, the database which could be out of sync if the webhooks fail enough times, and Redis which is even one more layer removed from the database.

I'm just not sure about what's the best way or conventional way to handle these problems given wanting to have accurate subscription information, easy to understand logic, and also make the process efficient.