Public work
Built from
Mular — mobile payments, transaction states and recovery
Worksheet
Download the transaction-state worksheet

I built this from the questions behind Mular’s send, swap and Naira-settlement flows. It is meant for wallets, bank transfers, remittance, checkout and any product where a vague “processing” state can leave someone unsure whether to wait or try again.

Start with where the money is

Backend events are necessary. Customer-facing language has a different job: “submitted”, “processing” and “failed” can each hide several materially different situations.

Define the user-facing state separately. It should say what has happened to the instruction, where the value is now, whether retrying is safe and which party owns the next move.

Flow momentWhat the user must knowRequired product response
Before commitmentThe exact amount, rate, fee, recipient and expected delivery.Show the full cost before the irreversible action. Keep every field editable.
Instruction acceptedWhether the instruction was received and whether value has been reserved or charged.Issue a stable reference and prevent an accidental second submission.
External handoff underwayWhere the value is and which outside rail or partner is being awaited.Name the handoff in plain language and give a realistic time band.
Confirmation delayedWhether value moved, whether retry is safe and when the product will check again.Keep the state open, block unsafe retry and expose the next review or support path.
Failed before value movedThat the balance or payment method was not charged.Explain the fix, preserve the entered details and make retry safe.
Failed after value movedThat value left one side but delivery did not complete.Do not collapse this into generic failure. Name the owner and recovery or refund path.
CompletedWhat the recipient or merchant received, when it arrived and the final amount.Show proof, a receipt and a support reference that uses the same transaction identity.
Reversed or refundedWhere the value returned, how much returned and when it becomes available.Show the destination, timing and any action still required from the user.

Separate three layers

A reliable payment flow keeps three related models distinct. The system state records what machines and partners have done. The user state is the strongest truthful sentence the product can show. The recovery state says who must act next and what evidence they need.

When those layers are collapsed, the interface often says “failed” while operations can still see money moving, or says “processing” after the user already needs to intervene.

  1. System state: record the events, timestamps, partner responses and money movement.
  2. User state: say what is known without exposing irrelevant infrastructure language.
  3. Recovery state: assign the next action to the user, support, an operator or an external rail.
  4. Support state: make sure the support team sees the same status and reference the customer sees.

Run the duplicate-risk test

The most dangerous recovery control in a payment product is a retry button whose consequences are unclear. Before exposing retry, answer the questions below for every delayed and failed state.

  1. Can submitting again create a second charge or payout?
  2. Can the product prove that the first instruction was rejected rather than merely delayed?
  3. Is the retry idempotent across the product, payment partner and payout rail?
  4. Will the user keep the original amount, rate and recipient details?
  5. Can support trace both the original attempt and the retry without merging them?
  6. If retry is unsafe, does the page state exactly when the user should check again?

Use the worksheet

The downloadable sheet gives each state one row and forces the team to name the user-facing status, money location, wait expectation, retry safety, state owner, support evidence and recovery path. Complete it with design, engineering, operations and support in the same room.

Every state should be actionable without claiming more than the system knows. Friendlier labels alone do not solve the problem.