A referral counter is never just a counter

I started with counter++. Then I had to explain where the number came from, and the referral system grew identities, states and history.

2 min read

The first referral system in my head looked more or less like this:

someone registerscounter++

Two lines, job done.

Then the questions started

Those two lines immediately raised questions. What if the person never confirms their email address? What if the browser retries after a timeout, even though the first request succeeded? What if two records belong to the same person? What if a referral is rejected later, or someone on the team fixes a mistake manually?

A total without a history

A number like 17 referrals only tells me the current result. It doesn't tell me why the result is 17, and that matters as soon as a reward depends on it.

Clicks, registrations and referrals

The first change was to stop treating a click as a referral. A click is useful telemetry. A registration is an event. The referral itself is a campaign-scoped relationship between two stable identities. Email addresses get corrected, verification arrives late and requests repeat, but none of that should turn the relationship into a new person.

An explicit lifecycle

Each referral now moves through explicit states: created, waiting for verification, verified, eligible, rewarded or rejected. The visible counter is derived from those records. It's convenient for the website, but it's no longer the source of truth.

Keeping the facts

I also keep the facts that changed the state: the referral was created, verified, rejected, rewarded or revoked. With those I can answer better questions: which referral changed the number, whether a retry repeated the operation, why a reward appeared, and whether I can rebuild the current state after changing a rule.

That may sound like a lot of machinery around a link somebody sends to a friend. It is. :) But the link is the easy part. Identity, verification and history are where the work is.

That was the point where CrowdRelay stopped being a counter and became something I could trust.

Loading…