Book a call

Case study 02 — Anlytic

Telling two payment failures apart

Owning the subscription lifecycle, and never removing access from someone who had already paid.

  • Full-stack lead
  • Go
  • React
  • PostgreSQL

Full

subscription lifecycle

Verified

provider callbacks

Live

plan changes, no refresh

The problem

Signup, upgrades, cancellations, trials and failed payments, across web and desktop. The happy path is the easy half. The provider is eventually consistent, its notifications arrive late or out of order, and two very different situations can look nearly identical when they land.

How it fits together

How a failed payment is classified activepayingwhich failure?still onretry, keep accessclosedaccess removedrenewalexhausted◀ the branchthat matters
Two failures look alike in the payload and mean opposite things. Everything in the design exists to tell them apart before acting.

What I did

Decide, do not accept

Incoming events are translated into our own view of what a customer's payment state is, rather than treated as the truth on arrival.

Separate the failures

A renewal that failed on a paying customer and a first payment that never completed are handled apart, so an existing plan is never closed by the wrong branch.

Tell the room

State changes propagate through the platform and reach open sessions directly, so a plan change is visible without a reload.

The hard part

The failure that mattered was never a missing notification. It was a misread one. Cutting off someone who had already paid is a far worse outcome than briefly not knowing, so the design is built to be uncertain safely.

Stack

  • Go
  • React
  • PostgreSQL
  • Kafka
  • WebSockets
  • Stripe

Written at the level the reasoning survives. Internal specifics are left out on purpose.

← All work

Next step

Got something stuck?
Let's look at it together.

Send the shape of the problem — a repo, a diagram, or three paragraphs of frustration. I'll reply with what I'd do first and what it would take.