Case study

Time Doctor: moving billing for 280K+ users from Stripe to Paddle

Core parts of an event-driven billing service on NestJS and GCP Pub/Sub, live in about 9 months.

In short

Time Doctor, a workforce analytics SaaS with 280K+ active users, needed to move subscription billing off a legacy service tightly coupled to Stripe. Core parts of the new event-driven billing service were built on NestJS microservices and GCP Pub/Sub, with idempotent Paddle webhooks and an auditable event trail. It went live in about 9 months and contributed to about $18M a year in savings.

Client
Time Doctor, USA
Role
Integrations Engineer
Users
280K+ active
Time to live
About 9 months
Result
About $18M a year in savings contributed

Workforce analytics SaaS · USA

Time Doctor
timedoctor.com ↗

Integrations Engineer, core billing services

Moving subscription billing for 280K+ users from Stripe to Paddle while the business kept running.

Context

Billing lived inside a legacy service tightly coupled to Stripe. Subscriptions and churn were hard to manage, and partner integrations depended on the same code.

Constraints
  • Live revenue for 280K+ active users
  • Partner and third party integrations had to keep working
  • Every subscription change had to be traceable
Key engineering decisions
  • Billing split into NestJS microservices that communicate through GCP Pub/Sub events, so subscription, churn and partner flows can change independently
  • Every Paddle webhook handled idempotently, so a retried delivery never applies twice
  • An auditable event trail for each subscription and churn change
  • Legacy partnership services and their data moved onto the new platform with minimal disruption
  • Infrastructure in Terraform, with 24/7 monitoring and alerts in Datadog
Results
280K+active users on the new billing
9 monthsto go live
$18Ma year in savings it contributed to
Simplified Time Doctor billing architecture: Paddle webhooks pass an idempotency check, then GCP Pub/Sub fans events out to subscription, churn and partner services, with state and an event trail in MongoDB and Redis.Paddlebilling providerwebhooksWebhook intakeidempotency checkGCP Pub/Subevent busSubscriptionsNestJS serviceChurn and lifecycleNestJS servicePartner integrationsthird party APIsaudit trailMongoDB · Redisstate and event trailTerraform infrastructure · Datadog monitoring and alerts, 24/7
Simplified architecture. Service names are descriptive.
NestJSGCP Pub/SubMongoDBRedisPaddleTerraformDatadog

Lessons for your project

What carries over to other systems

  • Make every webhook idempotent firstProviders retry deliveries. Deduplicating them is what stops a retry from charging or changing a subscription twice.
  • Publish billing changes as eventsWhen subscription changes go out as events, other services stop depending on one payment provider.
  • Keep an auditable trailEvery subscription and churn change recorded as an event makes support, finance and audits straightforward.
  • Monitor money flows from day oneInfrastructure in Terraform and 24/7 alerts in Datadog catch payment problems before customers do.

Questions

Common questions

Anything else is easier to answer on a short call.

Why move from Stripe to Paddle?

At Time Doctor the legacy payment service was tightly coupled to Stripe, and subscriptions and churn were hard to manage. The new service on Paddle made billing event-driven, auditable and no longer tied to one provider.

How do you migrate billing without disrupting customers?

Billing changes are published as events, every webhook is handled idempotently, and legacy partner services and their data move across with minimal disruption, with 24/7 monitoring throughout.

Can you run a similar migration for us?

Yes. It starts with a 1–2 week discovery and architecture sprint, priced at $1,000 to $2,000, that maps your billing flows and the safest path between providers.

Tell us what you need to build or scale.

Engagements start with a 1–2 week discovery sprint, $1,000 to $2,000. Email