DEV Community

Daniel Parkson Tano
Daniel Parkson Tano

Posted on AI-assisted

Designing Fee Engines for Different Payment Rails

Making fees transparent when providers calculate and collect them differently.

Fees seem simple until a product supports several payment rails.

One provider may deduct a fixed fee from the recipient amount. Another may charge the platform separately. A bank transfer may use a percentage with a minimum, while a wire transfer uses a flat charge. Some fees may be waived above a transaction threshold or after sufficient monthly activity.

A single fee field cannot explain all of these outcomes.

Separate the amounts in the quote

A payment quote should distinguish:

send amount
customer fee
total sender debit
provider request amount
provider fee
recipient amount
fee currency
Enter fullscreen mode Exit fullscreen mode

These values may be expressed in different currencies. A fee charged in the receiving currency should not be subtracted blindly from the sending wallet.

Model who absorbs the provider fee

Suppose the recipient should receive exactly 1,000 units and the provider deducts 50.

If the platform sends 1,000, the recipient receives 950. If the product promises an exact recipient amount and the platform covers the provider fee, the provider request may need to be 1,050 while the customer quote still shows a recipient amount of 1,000.

That policy should be explicit:

provider_amount = recipient_amount
if fee_policy == "platform_covers_recipient_fee":
    provider_amount += quoted_provider_fee
Enter fullscreen mode Exit fullscreen mode

Do not hide this adjustment in an adapter without recording the quoted and submitted values.

Configure fee rules as data

Fee rules change more frequently than transaction code. Store configurable values such as:

  • percentage;
  • flat amount;
  • minimum fee;
  • maximum cap;
  • transaction waiver threshold;
  • monthly activity threshold; and
  • rail-specific overrides.

Only one applicable active configuration should exist for a given scope. Changes should be auditable.

Record fee outcomes in the ledger

When a fee is charged, create a financial record. When it is waived, preserve the waiver reason and threshold used.

For monthly maintenance, use a deterministic account-and-period reference so concurrent workers cannot charge the same month twice.

Return concise fee information to clients

The API should provide the values the interface needs without forcing it to recreate fee logic. If a fee or cap is zero, the client can omit it. If a fee is waived, the API can return the effective fee as zero along with short eligibility information.

The backend remains authoritative for calculation; the frontend remains responsible for clear presentation.

The design principle

A fee engine translates commercial policy and provider behavior into explicit financial amounts.

The quote, sender debit, provider submission, recipient credit, and recorded fee must reconcile. If those values are not separately represented, the customer experience and financial reporting will eventually disagree.

LinkedIn post 12A

“Fee” is not one number in a cross-currency payment.

You may need to distinguish:

• customer fee

• total sender debit

• provider fee

• provider request amount

• recipient amount

• fee currency

When the provider deducts a fee from delivery, sending the quoted recipient amount may underpay the recipient.

PaymentFees #Fintech #ProductEngineering #Accounting

Top comments (0)