Users are facing issues with state synchronization between Paddle, their backend, and the UI, leading to discrepancies in user entitlements after upgrades/downgrades. A more robust synchronization mechanism is needed to ensure consistency across all platforms.
**I thought billing would be the easiest layer.** You build the infrastructure first. Multi-tenant architecture, roles, permissions, module system, subscription tiers, internal APIs — all the parts that actually make the system work. Then you add billing. At least that’s what I thought. I’m building something closer to a **SaaS operating system** than a single SaaS product. One core platform where different applications run on the same infrastructure layer. Which means billing isn’t just “charge a user”. It has to control: • feature access • module permissions • tenant limits • subscription tiers • upgrade and downgrade logic • scheduled plan changes • internal entitlement systems Basically the billing layer becomes a **control system for the entire platform**. That’s where things started getting… complicated. # The hidden complexity of Merchant-of-Record billing I chose **Paddle** because the Merchant-of-Record model solves a lot of problems: • taxes • global compliance • VAT • legal overhead • subscription infrastructure Which is great if you’re building a normal SaaS. But when billing is connected to a deeper system architecture, the complexity shows up quickly. The real challenge becomes **state synchronization**. Between: Paddle your backend your internal entitlement system and the frontend UI In theory everything should stay aligned. In reality you get situations like: • a user upgrades but the platform still shows the previous entitlement tier • a downgrade is scheduled but internal modules still think the user is on the higher plan • webhook arrives but UI state hasn’t refreshed yet • subscription preview shows one thing while internal pricing logic shows another Individually these are small issues. But inside a platform where billing drives system permissions, they stack up. # The part nobody talks about Billing in a SaaS OS becomes a **distributed state system**. Your database knows one version of the truth. The billing provider knows another. Your UI may still display a third. And suddenly users see: “Free plan” …while they already paid. # Sandbox reality Another interesting thing I ran into: The **Paddle sandbox behaves slightly differently from production** in subtle edge cases. Which means debugging upgrade/downgrade flows becomes harder when your system relies on: • preview calculations • scheduled plan changes • proration logic • webhook event timing # What I ended up doing A few rules became mandatory. 1. Backend subscription endpoints must be the only source of truth. 2. Webhooks must drive entitlement changes, not checkout responses. 3. Every UI component must read from the same subscription state. 4. Expect race conditions and design around them. # The irony Building the platform core was easier. Multi-tenant architecture. Modular feature system. AI integrations. Analytics. All of that behaved predictably. Billing… did not. # Curious what others building infrastructure-level SaaS experienced For those running **platform-level SaaS systems** (not just single apps): How did you handle billing as a control layer? Did Paddle integrate smoothly with your internal entitlement logic? Or did it become the hardest part of the system?