Event-Driven Fintech2023 to 2026

Campaign P&L Engine

The campaign engine behind partner rewards at a leading Southeast Asian personal-finance platform: campaigns, gifts and partner-reported applications.

Watch the explainer: Campaign P&L Engine, 75 seconds

Watch the 75-second narrated explainer. English captions on.Read the transcript

TL;DR

An event-sourced P&L and cost-reconciliation engine on Rails 8, with additive-only API contracts keyed on stable UUIDs.

Role
Backend Owner
Timeline
2023 to 2026 · 3 years
Stack
  • Rails 8
  • PostgreSQL
  • Rails Event Store
  • Kafka
  • Sidekiq
  • OpenAPI

01

Context

Profitability lived in spreadsheets, with no shared data model, no lifecycle and no reconciliation against what was actually paid out. And because a downstream operations platform consumed this engine's APIs, every contract decision had long-range consequences.

02

What I built

  1. A P&L subsystem from first principles: provider-reported applications, lump-sum monetising events and expiring forecasts, with transactional CSV ingestion and row-level error reporting.
  2. An incentive-cost reconciliation service: an event-sourced reactor books an approximate cost the moment a gift is issued, and an async job later reconciles it against actual purchase-order costs, with a feature-flag rollback path that got used.
  3. Claims lifecycle automation, including fixes for the race conditions that emerge when events arrive out of order.
  4. External API contracts designed additive-only, documented in OpenAPI in the same branch, always keyed on stable UUIDs rather than editable names.
  5. A Rails 8 and Ruby 3.4 upgrade delivered through staged rollouts with disciplined production reverts, plus a scheduled end-to-end regression suite with a documented scenario matrix.

03

Engineering judgment

API surface area was treated as a liability to be minimized: the default test for any new capability is the design that adds no new endpoints, no new auth scopes and no new routes. Contracts were designed additive-only against stable identifiers, which later allowed a parallel next-generation system to adopt them as its compatibility target.

04

Outcome

Campaign profitability became a queryable system instead of a spreadsheet ritual, and the engine's external contracts now anchor a downstream fulfilment platform and a next-generation campaign system.

05

Transcript

Read the 75-second explainer as text

Is this campaign actually profitable? Nobody could answer precisely. The numbers lived in spreadsheets, never reconciled against actual payouts.

The Campaign P&L Engine powers partner rewards at a leading Southeast Asian personal-finance platform. First, a P&L model: provider-reported applications, lump-sum monetising events, and expiring forecasts, loaded by transactional CSV ingestion, with row-level errors. The moment a gift is issued, an event-sourced reactor books an approximate cost. Later, an async job reconciles it against actual purchase-order costs, with a feature-flag rollback path that got used.

External contracts are additive-only, keyed on stable UUIDs, never editable names. So a next-generation system adopted them as its compatibility target. Rails 8, PostgreSQL, Rails Event Store, Kafka and Sidekiq, owned for 3 years. Profitability became a queryable system, not a spreadsheet ritual.

Approximate now. Reconciled later.

Work with me

Have a system like this that needs to reach production?

Book an intro call to talk it through, or email me a few lines about what you are building.