1. Blog
  2. System breakdown

System breakdown: why a refund takes days when the payment took seconds

You cancel an order and the app says the refund has started. Your bank shows nothing for days. Here is where the money is in between, and which parts of the delay a shop can and cannot change.

The Kolom team6 min read

On Sunday evening you book a "Later" delivery slot in the Mangrove app for Tuesday morning and pay $23.40 by card. On Monday your plans change, so you cancel. The app says "Refund of $23.40 started" straight away. You open your bank's app: nothing. Tuesday: still nothing. Later in the week a line finally appears.

For a slot booked days ahead, Mangrove takes the payment when you book rather than holding it until packing, because a hold on a card only lasts a limited time. So this time there is real money to send back.

The payment felt instant. Why is the refund so slow? The short answer: the payment was not really instant either. You just stopped watching once your order was confirmed.

Two clocks: approval and settlement

When you pay by card, two things happen at very different speeds.

  • Approval takes a second or two. Your bank checks the card and the balance and says yes, and the amount is held on your account. That is all the checkout screen waits for.
  • Settlement, the money actually moving between banks, happens later and mostly in batches.

When you pay, you only care about the first clock: your groceries are on the way. When you get a refund, you care about the second one, because nothing shows until the money arrives. Refunds travel from the shop's payment provider through the card network to your bank, and your bank decides when to show the credit. Some banks show a pending refund early; many only show it once it settles, which often takes a few working days.

That part is outside Mangrove's control. Everything before it is not, and that is where a good design shows.

Where the money is, step by step

App Refund API Ledger Provider Your bank Reconcile 1. cancel "Refund started" 2. two entries 3. job, key r-77 4. days 5. nightly report
Steps 1 to 3 take seconds and are Mangrove's own systems. Step 4 is the banks. Step 5 checks every night that the provider's report and Mangrove's ledger agree (the dashed line).
  1. The app asks for the refund. The refund API checks the order can be refunded and answers "Refund started". The words matter: it has started, it has not arrived.
  2. The ledger records it at once, as two entries. Mangrove keeps money in a double-entry ledger: every movement is written as two rows that balance, here "sales −$23.40" and "owed to customer +$23.40". Rows are never edited. A mistake is fixed with new rows, so the history always adds up. Both rows go in one transaction (Transactions, ACID, isolation and locks explains why that matters).
  3. A background job calls the payment provider with an idempotency key made for this refund. If the call times out, the job retries with the same key, and the provider refunds once. Background jobs and idempotency builds exactly this job. The same idea protects payments, as the tap Pay twice breakdown shows.
  4. The provider passes the refund to the card network and your bank. This is the slow step, and the shop can't speed it up.
  5. Every night, Mangrove reconciles. The provider sends a report of everything it settled. A job matches each line to a ledger entry. Matches are closed. Anything missing, doubled or different goes to a queue for a person in finance to check.

Why reconcile at all?

Because steps 3 and 4 cross a boundary Mangrove does not control. A refund call can time out after the provider did the work. A provider can refund a slightly different amount after a currency rounding. A support agent can refund by hand in the provider's dashboard and forget to tell anyone. Each of these leaves Mangrove's ledger and the provider's records disagreeing, and without a nightly comparison nobody notices until a customer complains or the month's accounts don't balance.

Reconciliation is boring, and it is the reason the ledger can be trusted. It is also how Mangrove can answer a customer who says "I never got my refund": it can show the date the provider settled it and the reference the bank can trace.

What Mangrove can change

Mangrove can't make banks faster, but it can choose where the refund goes and what it says.

Refund to What the customer sees The trade-off
The original card Money back in their bank, after a few working days Slow, but it is the customer's own money in their own account
Mangrove balance Credit in the app at once Instant, because the money never leaves Mangrove's ledger, but it can only be spent at Mangrove
Nothing taken (held payment released) The hold disappears from the account Possible only while the payment is still a hold, for example a "Now" order cancelled before packing

The best answer is to offer the choice and say plainly what each one means. Many people pick the instant balance for a small amount and the card for a large one. For cash-on-delivery orders, about 35% of Mangrove's app orders, there is usually nothing to refund at all: the rider simply doesn't collect.

And the words: "Refund started on 21 Oct. Banks usually show it within a few working days. Reference R-77" beats "Refunded!" followed by a week of silence. The first sets the right expectation and gives the customer something to quote. The second creates a support ticket.

If you want to go deeper, Events, the outbox pattern and sagas covers how a refund that spans several systems is kept consistent when one step fails half way.

system designpaymentsreliability

Get the next one by email