We launched on HN back in 2018 (https://news.ycombinator.com/item?id=17610735), were in YC that same year, and have since helped 20k apps power their subscriptions and in-app purchases.
I held back from releasing something like this for years as I didn't quite think we had the capacity to do it well, but we've reached that point now and I think we've released some aggregate stats on subscription consumer mobile apps the prior to this were only available inside Apple or Google.
There are handful of competitors out there; I've heard mixed things and am obviously very biased. They do handle some things better than us, but on balance I think our product is more battle tested and reliable.
We are also getting ready to roll out a very significant update to our underlying abstractions with the release of our developer API sometime in early 2023 that I think will put us far out and ahead.
If you're at the just getting started stage, I have no hesitation saying to go with us, we've got 20k other apps using RC today and another 200 going live every week. We won't charge you anything until your app makes $10k/mo.
I've made CEO-noise again and hopefully we can keep pushing on these two.
- Expiration webhooks are not always sent, so customers keep their entitlement way after they should: Ticket 13919 (although it's been spread across a few as it must close them after a while or something)
- A much more urgent issue I opened a couple weeks ago: Customers that cancel and then re-subscribe for a trial at some point in the future have no webhook sent at all. The dashboard says their trial has started, so revenuecat knows the trial exists, but no webhook event is actually sent for it. This is causing a mess of customers who sign up but don't get their entitlements and end up asking for a refund or sending an angry email. Ticket 16016
- I've noticed a bunch of weird bugs, sometimes only affecting one customer so I haven't opened a ticket, but it just makes me question things. For exmaple, we implemented trials in April but our dashboard shows trial signups and conversions from last year. That is not possible, so I question the accuracy of the trial stats as well. Another issue from long ago was that the product_change event on android commonly sends the wrong new product ID, so we just have to ignore it. I was told this is a limitation of the play store though, but it wasn't obvious from the docs back then (not sure if it is fixed now). This makes it difficult to reflect what plan a user switched to within the app, since the product change event can't be trusted. Like most of the issues, the RC dashboard shows it correctly, it is just the webhook that is wrong (which is why I couldn't understand the response that it is a play store bug, when RC shows it right on their end but sends the wrong/old ID in the webhook) Since android downgrades are immediate, the initial_purchase that follows will actually set the correct ID, so that is the workaround for now that I found. (Hopefully I got that right, I'm reading the comments for the workaround we added)
I really want to see revenuecat work and succeed, because it is a great idea and for the most part made implementing subscriptions much easier, there are just a lot of edge cases we keep running into. Support is also not the most helpful, but I understand they are probably swamped. The android bug I mentioned above, the solution was to just use the RC api to fetch the status rather than using the webhook. Why would the API return a different ID than the webhook sent 50ms before? I'm not sure why there is such a disconnect between webhooks and what the API/dashboard returns. It would also be great if you could add a dashboard for support tickets rather than having to use email, it would keep things more organized, as I often need to contact support directly because the community tech support forum is a graveyard. I understand technical issues should be directed there, but they often sit for weeks with no response. Even with these issues I'd still recommend RC in general though. If these issues are happening with a company who's purpose is to handle them, I can't imagine how difficult it would be to implement a subscription system from scratch.
I dug into both tickets. A bunch of failures both in product and process on our part. Going to dig in more.
Then why would companies bother hiring people in expensive locations if they can hire another developer in a foreign country for half the price?
In practice, companies that adopt location-independent salaries don't automatically pin their compensation to the most expensive locales. They pick a midpoint compensation that is good enough to attract remote workers who can't do any better locally, but they turn away a lot of developers in expensive places like Seattle or SFBA who know they can do better locally.
For example, when I implemented the PRODUCT_CHANGE event I expected it would notify me of the new product, but that is not the case on Android which led to bugs with some customers. It turns out that only iOS sends the new_product_id, so it is impossible to know from this event what the new product should be to display it in the app. Since upgrades/downgrades are immediate on Android, it turns out that the solution was just to not handle that event on Android since the renewal event would override the product anyways. (but sometimes the events came out of order, which is what led to bugs when PRODUCT_CHANGE was after RENEWAL).
There are a lot of cases where events in the dashboard are totally out of order and don't make sense, like showing a customer purchasing the lesser plan, then renewing for the upgraded plan, and then switching from the lesser to the upgraded plan 10 days later. How could that be possible? The switch should have been between the renewals, so it's very confusing to debug.
I've been told that now the recommended approach is to ignore all the webhook data, and simply call the RevenueCat API to get the entitlement and subscription status - however I asked how to parse this into something meaningful and didn't get a good answer. I would like to know the users current entitlement, and the current subscription (which can be different than the entitlement). For example, if the user downgrades, their entitlement may still be the upgraded plan for a while, but the app should reflect that they are no longer subscribed, or that they are subscribed to a different plan. For the entitlement it is easy I think, just choose the highest entitlement level to use. For the subscription, maybe choosing the last renewed one would work? But there are so many complexities with downgrades, upgrades, crossgrades I don't know if that is true. The answer from support was basically that they didn't know, yet this is an absolute must for almost any app - there has to be a way to display what the user is currently paying (or not paying) for, linking out to the native UI is not an option as it's not user friendly and cannot be displayed cross platform (I want the website to also reflect what they are paying for). My big concern with this is also, why does the API supposedly return the correct data but the webhook doesn't? If I am calling the API 10ms after receiving the webhook, why can't the webhook just deliver correct data instead?
Another current issue I discovered the other day was that grace periods are no longer working. The RevenueCat dashboard shows that they are getting a 7 day grace period (the expiration date in the dashboard is correct), yet in the webhooks I am getting the wrong expiration, one that is only a day away. Apparently this is due to a change by Google and a fix is (maybe?) on the way? But it caused a lot of issues that I didn't expect.
Basically RevenueCat's promise is great, it has saved a ton of time but isn't quite there on fully abstracting all these native edge cases away, they crop up in the API occasionally, and the proposed fix to use the API instead of the webhook data is half baked when support has no idea how to actually parse it to get the current subscription that should be displayed to the user (in the case that they upgraded/downgraded and have more than one). I love the idea but I'm hesitant to recommend it to anyone because lately it's been causing a lot of headaches with customers having billing issues due to these inconsistencies.
Would you mind dropping me an email jacob@revenuecat.com? I think for our long term viability we need to have the trust of people who care about edge cases like this. I’d love to hear more.
Obviously, Stripe is the gold standard and I think we have a hard time, but we're hoping to improve the developer experience even more this year.
I would like to move certain users (for instance by recommending that in a newsletter, or handing out coupons for the Stripe subscription) from their current iOS subscription to Stripe, and it is hard to make the overlap smooth. Does Revenuecat have some solution to this?
For this particular case it’s tricky on iOS since you can’t programmatically cancel a subscription on iOS. It must be initiated by the customer on the device.
However, if you navigate that UX challenge, you can use our events and webhooks to make a smooth experience guiding a user through the process. Hadn’t thought of this before, but you could probably pre-authorize a stripe token, then ask them to cancel on iOS, then wait for the webhook from us, then finish the transaction and track it to the same customer ID in RevenueCat.