$ cat projects/roigenius.md

RoiGenius

Revenue attribution SaaS — eight microservices in production, 89 integrated platforms

in production Aug 2024 — Present Tech Lead, Principal Systems Architect & General Manager (Interim CEO)

at a glance

Stage
In production since Aug 2025
Architecture
8 TypeScript/NestJS microservices, autoscaled containers
Datastore
PostgreSQL 15 tuned for high concurrency
Integrations
89 advertising and checkout platforms
Team
Cross-functional team of 3, plus executive duties

context

Co-founded with a partner and led end-to-end: engineering direction, product roadmap, and the general management of the company including cash flow and cloud cost governance.

the problem

Advertisers and checkout platforms each report their own numbers, and nobody can say which ad produced which sale. Attribution means ingesting every transaction and reconciling it against spend — across dozens of platforms that disagree about currency representation, timezone, and the meaning of the word "revenue".

The hard part is not volume. It is that a sale is not final when it happens: refunds, chargebacks and fees arrive days later, from a different system, sometimes under a different transaction identifier.

approach

What was tried — and, where it applies, what it taught. The second half is the part that usually gets edited out, and the part that is actually useful.

    • Eight services behind a shared ingestion path, with a calculator registry that standardises metric definitions across every integrated platform.

    learned Each new platform is a new accounting model, not a new API. The registry is what makes a new integration a one-day job instead of a one-week job.

    • Monetary amounts handled as fixed-point strings end to end — never floating point, never implicit rounding.

    learned Floating-point money is not a rounding inconvenience, it is a correctness defect that compounds silently across aggregate reports. The cent-divisor also differs by platform, so "the value" is not even a single convention.

    • Webhooks acknowledged immediately with processing decoupled asynchronously, backed by dead-letter queues and progressive retry windows.

    learned A platform that does not receive an immediate acknowledgement retries, and retries cause duplicate events. Rejecting bad input is cheap; reconstructing state after a dropped event is not.

    • A partitioning and index strategy built around the queries the product actually runs.

    learned The first version optimised writes. The product is read-heavy on aggregates, and the tuning had to be redone around that asymmetry.

outcome

Integration surface
89 platforms
advertising and checkout/gateway providers
Services
8 microservices
TypeScript / NestJS 11, containerised and autoscaled
Money handling
Fixed-point strings
no rounding drift in aggregates
Failure handling
Dead-letter queue with progressive retry
1h → 16h windows before dead

what I would do differently

The costliest lesson was that reconciliation, not ingestion, is the product. Plenty of teams can accept a webhook; far fewer can explain, six months later, why two reports disagree by one cent.

If I rebuilt it, the calculator registry would come first. It is the component that turns an unbounded integration problem into a bounded one.

artifacts

No public artifact: this work lives in private repositories. The description above is the citable summary.

Last reviewed against its sources. Back to top