Cross-Merchant Points Funding
Who funds cross-merchant redemption — launch a constrained Model 1 (earning-merchant-only + caps), architect the ledger for Model 2 (earner pre-funds a pool), reserve Model 3 (befday float).
Status: Accepted (direction); implementation phased
Date: June 2026
Decision: Resolve the cross-merchant funding question left open by befday Points Currency. Launch with a constrained Model 1 (redeeming merchant absorbs, redemption limited to the earning merchant in v1 + per-order caps), and architect the ledger for Model 2 (earning merchant pre-funds a central pool) so true cross-merchant redemption is config, not a rewrite. Model 3 (befday-operated central float) is reserved for a future where befday runs the currency as its own business line.
TL;DR
Points are a network-wide currency, but cross-merchant redemption raises: who funds a discount at B for points earned at A? Three models exist (redeemer absorbs / earner pre-funds / befday clears). Plan: ship constrained Model 1 (redeem only at the earning merchant, no clearing), record earning/redeeming shop from day one so Model 2 (earner pre-funds a pool) is a config flip, not a migration.
Context
befday Points Currency makes befday points a spendable currency: earned proportionally to spend, redeemable as merchant-funded credit at checkout. Its core unlock and hardest problem is cross-merchant redemption: points earned at café A become spendable at restaurant B.
The unresolved question: when a user redeems at B points they earned at A, B gives a real discount on a real sale. Who absorbs that cost?
Setel/Mesra sidestep this — they are effectively one funder (Petronas owns the stations). befday has many independent merchants, so the cost must be assigned explicitly. This decision picks the model and the migration path between models.
The three funding models
Model 1 — Redeeming merchant absorbs it
“Whoever takes the points, eats the discount.”
Points are a bearer instrument: when the user redeems 1,000 pts (= RM10) at B, B absorbs RM10 like accepting a voucher. The redemption lands as points_discount_cents on B’s order and settles in B’s books. No clearing, no pool, no inter-merchant accounting.
| Pros | Cons |
|---|---|
| Dead simple — it’s just a discount line | Unfair: B funds value A’s sale created |
| No central float or settlement engine | Popular/cheap merchants get dumped on by redeemers |
| Cost lands where the sale happens | Merchants cap/refuse redemption → network fragments |
| Bounded per-merchant liability (they control caps) | “Why fund café A’s loyalty?” → merchant churn |
Risk bearer: redeeming merchant. Good when merchants are similar in size/margin and trade redemptions roughly evenly (nets out). Bad when they don’t.
Model 2 — Earning merchant pre-funds a pool
“Whoever issued the points already paid for them.”
When A grants 1,000 pts, A pays a funding amount into a central befday pool (at settlement). When the user redeems at B, B is reimbursed from the pool. Cost stays with the merchant who got the original sale and chose to reward it.
| Pros | Cons |
|---|---|
| Fair: cost sits with the merchant who got the sale | Real clearing system — pool balance, settlement, reconciliation |
| Redeeming merchant B is made whole → happy to accept | Issuers pay now for points that may never redeem (until breakage) |
| Mirrors how miles / card points actually work | Cash-flow drag on issuing merchants |
| Breakage is an asset — unredeemed funds return to issuers/befday | More complex settlement statements |
Risk bearer: earning merchant (pre-paid); befday holds float. Good when you want fairness and will build settlement. The “grown-up” model.
Model 3 — befday clears a central pool (platform float)
“befday runs the bank.”
befday is the clearing house. Merchants pay a program fee (% of points-eligible sales or flat fee) into a befday-managed fund; befday funds all redemptions and reimburses redeeming merchants. Earn/redeem events aren’t tied to a specific merchant’s books — befday absorbs the matching risk.
| Pros | Cons |
|---|---|
| Cleanest merchant experience — pay a fee, never think about it | befday carries the liability — a mini financial product |
| befday controls economics (rates, expiry, breakage = margin) | Needs capital/float to cover redemption timing |
| Strongest network feel — one currency, one operator | Regulatory exposure (stored-value / e-money rules) |
| Breakage accrues to befday — a real revenue line | befday eats the loss if redemptions outpace fees |
Risk bearer: befday. Good when befday wants the currency itself to be a business line — heaviest lift, carries compliance risk.
Comparison
| Dimension | M1 Redeemer pays | M2 Earner pre-funds | M3 befday clears |
|---|---|---|---|
| Build complexity | Lowest | High | Highest |
| Fairness to merchants | Poor | Best | Good (fee-based) |
| befday liability | None | Float only | High |
| Breakage benefits | Redeemer (luck) | Issuer / befday | befday |
| Merchant churn risk | High | Low | Low |
| Regulatory exposure | Low | Low–med | High |
| Revenue for befday | None | Low | High |
Decision
Start with a constrained Model 1; architect for Model 2; reserve Model 3.
v1 — Constrained Model 1 (ship)
- Points-credit redemption is enabled only at the earning merchant (earn at A, spend at A). Delivers the wallet UX and validates demand with zero cross-merchant accounting.
- Redemption is a
points_discount_centsline on the order (merchant-funded), as befday Points Currency specifies. - Guardrails: per-order redemption caps + min redemption, to protect merchant margin.
- Effectively a spend-based evolution of Platform Stamps & Referral, without the financial-clearing risk.
Earning still accrues network-wide (points earned everywhere land in one wallet). Only redemption is constrained to the earning merchant in v1.
v2 — Cross-merchant via Model 2
- Flip on cross-merchant redemption backed by an earner-pre-funds pool.
- Each earn event records a funding liability for the issuing merchant; redemptions draw the pool; befday clears reimbursement to the redeeming merchant.
- Breakage (expired/unredeemed points) returns to the pool as an asset.
- Because the v1 ledger is built as if M2 is coming, this is a config + settlement-engine addition, not a rewrite.
Model 3 — reserved
- Pursue only if befday decides to operate the currency as a business line (program fees + breakage as revenue) and is ready for the float and compliance burden.
Trap to avoid
Do not launch full cross-merchant Model 1. That’s the version where merchants quietly resent funding each other, cap redemptions, and the network feel dies.
Data Model Impact (sketch)
Builds on befday Points Currency’s befday_wallets / befday_point_events. To keep v1 simple but M2-ready, record issuing + redeeming merchant on every event from day one, even though v1 doesn’t clear cross-merchant.
befday_point_events additions (over befday Points Currency)
| Column | Type | Notes |
|---|---|---|
earning_shop_id |
uuid | nullable FK → shops.id — where purchase points were issued |
redeeming_shop_id |
uuid | nullable FK → shops.id — where a credit_redeem was applied |
funding_model |
enum | redeemer_absorbs | earner_prefunds | platform — model in force at event time |
Capturing earning_shop_id / redeeming_shop_id in v1 means the data needed to settle Model 2 retroactively already exists when you flip the switch.
befday_funding_pool (M2 — added at v2)
| Column | Type | Notes |
|---|---|---|
id |
uuid | PK |
shop_id |
uuid | FK → shops.id — contributing (issuing) shop |
direction |
enum | contribution (earn) | reimbursement (redeem) | breakage_return |
amount_cents |
integer | funded / reimbursed amount |
point_event_id |
uuid | FK → befday_point_events.id |
settled_at |
timestamp | nullable — set at settlement run |
befday_program_settings extension
| Column | Type | Notes |
|---|---|---|
funding_model |
enum | active model (redeemer_absorbs default in v1) |
cross_merchant_redeem |
boolean | v1 = false (earning-merchant only); v2 = true |
max_redeem_per_order |
integer | per-order redemption cap (margin guardrail) |
min_redeem_per_order |
integer | minimum redemption to avoid penny-shaving |
Consequences
| Type | Consequence |
|---|---|
| Pro | Ships the wallet/currency UX in v1 with no clearing system and no financial-instrument liability beyond a normal voucher. |
| Pro | v1 ledger captures earning/redeeming shop, so the Model 2 upgrade is data-ready — no migration of historical events needed. |
| Pro | Fairness problem is solved on paper before it can cause merchant churn. |
| Pro | Clear escalation path (M1 → M2 → optional M3) tied to business readiness, not a forced big-bang. |
| Con | v1’s earning-merchant-only redemption is not yet the full network unlock — true cross-merchant spend waits for v2. |
| Con | Model 2 settlement engine (pool, clearing, reconciliation) is real backend work to schedule before v2. |
| Con | Model 3, if ever pursued, brings regulatory/e-money questions that need legal review. |
Resolved Decisions
| Question | Decision |
|---|---|
| Who funds cross-merchant? | v1: redeemer (but redemption locked to earning merchant); v2: earner pre-funds |
| Launch model | Constrained Model 1 — earning-merchant-only redemption + caps |
| Target model | Model 2 — earner pre-funds a central pool (fair, breakage = asset) |
| Model 3 (befday float) | Reserved — only if operating the currency becomes a business line |
| Data readiness | Record earning_shop_id / redeeming_shop_id from v1 to enable M2 retro |
| Margin guardrails | Per-order min/max redemption caps from v1 |
Open Questions
- Funding rate (M2): how much does an issuing merchant pay into the pool per point granted — equal to redemption value, or discounted (spread funds the program)?
- Settlement cadence (M2): how often does the pool clear (per transaction, daily, monthly)?
- Breakage split (M2): when points expire, does the funded amount return to the issuing merchant, befday, or split?
- Margin caps: concrete v1 values for
max_redeem_per_order/min_redeem_per_order. - Opt-in vs default (v2): is cross-merchant redemption automatic for all merchants, or opt-in per merchant?
- Model 3 trigger: what business conditions (volume, regulatory clearance) would justify moving to platform-operated float?