Section 12 of 14
Billing & Plans
What This Does
The app has 4 billing tiers: Free (20 orders/month), Starter ($9.99, 100 orders), Growth ($24.99, 500 orders), and Pro ($49.99, 2000 orders). The billing system checks limits before processing and increments usage after successful pushes. Beta testers get 2x limits and 50% off.
Why It Matters
This is how the business model works. The split between 'check' and 'increment' is critical — we check limits BEFORE processing to avoid wasted work, but only increment AFTER a successful push to avoid counting failed orders.
How It Works
- 1.checkUsage() is called during pipeline Step 6 (before any ShipStation work). It reads the current count and compares against the plan limit.
- 2.If the limit is reached, the order is failed with a BILLING error and a plan limit email is sent.
- 3.If usage is at 80%+, a warning email is sent (once per billing cycle).
- 4.incrementUsage() is called during pipeline Step 11 (after successful push to ShipStation).
- 5.Billing cycles auto-reset every 30 days. The reset also clears the 80% warning flag.
- 6.Beta testers get 2x order limits and 50% off paid plan prices.
The Code
Key Decisions
- ●Check vs increment split: checking before processing prevents wasting ShipStation API calls on orders that can't be billed. Incrementing after push prevents counting orders that failed.
- ●30-day rolling cycles (not calendar month) for simplicity and fairness.
- ●80% warning gives merchants time to upgrade before they hit the wall.
- ●Only the Pro plan supports multiple warehouse countries (a feature differentiator).
What Could Go Wrong
- ●If we incremented before the push and the push failed, the merchant would lose a processing credit for nothing.
- ●If we checked but didn't increment, merchants could exceed their limits.
- ●Race condition: two orders checking simultaneously might both pass the limit check. The increment is atomic (Prisma { increment: 1 }) so the total stays correct, but one extra order might slip through.