Skip to Content
ConceptsArchitecture

Architecture

Four systems make up the retention engine: the widget in your customer’s browser, your server, the Unchurn backend, and Stripe itself. The widget renders the flow, your server says who’s allowed to open it, Unchurn’s engine scores eligibility and routes offers, calls Stripe on your behalf, and Stripe stays the source of truth. This page maps the trust boundaries between them so a security review takes ten minutes.

The shape

Your server never talks to Stripe in the cancel flow. That’s on purpose — you don’t wire Stripe SDK calls into your cancel button, you don’t think about retries, and your Stripe error surface stays the size it is today.

What each system owns

The widget (browser). Shows the UI. Holds no credentials beyond the short-lived signed token your server issued. Cannot talk to Stripe directly; every request goes through Unchurn’s backend. Ships as a hosted CDN runtime plus npm packages for React and Next.js.

Your server. Authenticates the customer with your existing auth (cookies, sessions, whatever you already use). Maps that customer to their Stripe subscription. Issues a signed token saying this customer is allowed to open the cancel flow for this subscription, valid for 600 seconds.

The Unchurn backend. Verifies the signed token. Reads the subscription from Stripe through your Stripe Connect link. Runs eligibility checks per offer. Makes the Stripe change when an offer is accepted, and verifies it by reading the subscription back. Records every session, decline, and acceptance in your dashboard.

Stripe. The source of truth. Receives the actual changes — pauses, discounts, scheduled cancellations, trial extensions, plan changes — and returns the resulting state, which Unchurn reads back before reporting success to your app.

Trust boundaries

Three boundaries, three pieces of evidence:

BoundaryWhat’s checkedIf it fails
Browser → Your serverYour existing authYour server returns a 401; no token is issued.
Browser → UnchurnCryptographic signature on the token + expiryUnchurn returns a 401; no Stripe call is made.
Unchurn → StripeStripe Connect grant validitySession is flagged as failed; you’re notified in the dashboard.

A captured token is replayable until it expires (600 seconds). Rotate your Unchurn secret from the dashboard if you suspect a leak, and don’t log signed tokens to your application logs.

Stripe Connect, not API keys

Unchurn connects to your Stripe account via Stripe Connect OAuth — you don’t paste API keys into our dashboard. That gives you three things:

  • You can revoke Unchurn’s access from your Stripe dashboard at any time, instantly.
  • Test mode and live mode are connected separately; connecting one does not connect the other.
  • We never receive or store your Stripe API keys. We use Stripe Connect’s connected-account identifier and act on your behalf through Stripe’s standard Connect mechanism.

Unchurn requests Stripe’s read-and-write Connect permission — required to apply pauses, discounts, plan switches, trial extensions, and scheduled cancels on your behalf. Read-only would let us show the dashboard but not run the flow. We use the permission only for the subscription reads and retention changes documented in The five offers; you can audit and revoke this access from your Stripe dashboard at any time.

What Unchurn does not store

  • Your Stripe API keys (we use Stripe Connect’s connected-account identifier instead).
  • Your customer’s payment method details.
  • Your customer’s email or PII beyond what’s needed to show the flow.

What we do store: the connected-account identifier for each mode, the session ID, the subscription ID, the offer evaluations, the outcome, and the cancel reason or feedback the customer provided during the flow.

Deployment shape

Your server runs wherever your app runs. Unchurn doesn’t require any new infrastructure on your side beyond the one route handler that signs tokens. The Unchurn backend runs on managed cloud infrastructure with a Postgres database for sessions and configuration.

Where to go from here