$ cat projects/roigenius.md
RoiGenius
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
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.