All posts

Attribution when you do not own the website

Backend notes from Elevista — embeddable tracking, Kafka, PostgreSQL plus MongoDB, and Temporal for flows that outlive a single HTTP request.

  • Kafka
  • Temporal
  • NestJS
  • event-driven
  • PostgreSQL
  • MongoDB
Kafka and Temporal event attribution pipeline

Elevista pays creators for referral outcomes — sign-ups, purchases, the usual attribution problem. A promoter drops a script on a site Elevista does not control. Events show up with a referral code, maybe a page URL, often no logged-in user yet.

I worked on the backend under a direct contract with the London team. NestJS, PostgreSQL, MongoDB, Kafka, Temporal. Volume during my time was modest — on the order of a hundred interactions a day — but the product needed room to grow without a rewrite.

Keeping the ingest endpoint fast

The tracking script posts events. The API validates and normalizes them quickly, then gets out of the way. ThumbmarkJS helped stitch anonymous sessions before account creation — useful when attribution spans multiple visits.

Deduplication, rule evaluation, and reporting rollups sit behind Kafka so ingestion stays responsive when consumers lag. Publishing at the boundary kept HTTP handlers boring, which is what you want at the edge.

PostgreSQL for money, MongoDB for events

PostgreSQL holds accounts, campaigns, reward rules, and payout-related entities — anything that needs transactions and constraints. MongoDB takes high-volume event-shaped traffic for analytics and time-series reporting.

We could have forced all events into relational tables. It would have worked for a while and hurt later. We could have put financial config in documents. That would have hurt immediately. The split matched how the product actually read data, not how a diagram looked in a deck.

Video workflows that outlast one request

Some creator flows clip a video segment, hand off to an external transcoder, mint a share link, and track engagement. That is not one request/response cycle. Temporal coordinated steps and retries so a failed transcode did not orphan the referral context.

A queue plus idempotent consumer is enough for plenty of products. This was not one of them — external systems, retries, and user-visible delays were part of the flow.

Where we put the business rules

Campaign rules lived as data where we could change them without redeploying. Deduplication logic stayed explicit and tested — that is where attribution products quietly lie to you if you are careless.

Kafka at the edge, boring handlers, workflows only where external systems and retries are part of the user journey. Nothing clever for its own sake.