Skip to content
16px
Why All UPI Apps Feel the Same Speed
UPIFinTechIndiaSystem DesignPaymentsNPCI

Why All UPI Apps Feel the Same Speed

PhonePe and Google Pay feel equally fast because the bottleneck is not the app — it is NPCI, bank cores, SAGA-style safety, idempotency, and the same ledger rails behind every PSP.

April 6, 20266 min read

You tap pay on PhonePe. Your friend taps pay on Google Pay. Both reach the other person in roughly two seconds. Nobody wins on speed.

That is not a coincidence. That is architecture.

The Question Worth Asking

If PhonePe has hundreds of engineers optimizing their app, and Google has one of the best infrastructure teams in the world, why does the same ₹100 transfer take the same time on both?

The honest answer is that the bottleneck is not the app. It is never the app.

What Actually Happens When You Hit Pay

Most people assume the app processes the payment. It does not.

What actually happens:

  • Your app talks to its own PSP backend (PhonePe, Paytm, Google Pay each have their own)
  • That backend validates your request and forwards it to NPCI
  • NPCI figures out which bank owns your VPA and which bank owns the receiver's VPA
  • NPCI tells your bank to debit
  • NPCI tells the receiver's bank to credit
  • Both banks confirm
  • You see success

The app is not moving money. It is a well-designed form that sits in front of the real system.

The real system is NPCI.

NPCI Is a Router, Not a Bank

This is the most important thing to understand.

NPCI does not hold money. It does not have accounts. It is a switch, like a traffic controller at a busy intersection.

When you type alice@okaxis as the destination, NPCI does not look up Alice directly. It does a two-step resolution:

First, it looks at the handle. okaxis tells NPCI: this is an Axis Bank VPA registered through a particular PSP.

Then it resolves the PSP to an actual bank adapter and routes the request there.

That resolution is fast because it is an in-memory lookup. Literally a map lookup. O(1). This is why VPA resolution never feels slow.

The slow part is never NPCI. The slow part is always the bank.

Why Banks Are the Bottleneck

Every bank runs its own core banking system. Most of these systems were built decades ago. They are reliable and battle-tested, but they are not fast by modern standards.

When NPCI sends a debit request to Axis Bank, Axis has to authenticate the account, check balance, apply the debit atomically, and confirm back to NPCI.

That round trip takes somewhere between 300ms and 800ms on a good day. Sometimes more.

This is why rewriting the PhonePe app in Rust does not help. The app is not the problem. The app takes maybe 100ms to talk to its own backend. The bank takes 500ms to do anything. You cannot optimize your way out of someone else's core banking system.

How the Transaction Actually Stays Safe

The debit and credit are two separate operations on two separate banks. There is no shared database locking them together. So what happens if one succeeds and the other fails?

This is where the SAGA pattern comes in.

Instead of trying to make both operations atomic at the database level (which is impossible across two independent banks), the system uses compensating transactions.

The flow looks like this:

text
1debit sender's bank
2  success -> credit receiver's bank
3    success -> done
4    failure -> refund sender's bank -> mark failed
5  failure -> mark failed

If the credit to your friend's bank fails after your bank was already debited, the system does not just shrug. It initiates a refund. That refund is what gets you your money back when a payment fails mid-way.

This is not a special error case. It is the designed behavior. The system expects failures and has a plan for each one.

Why You Never Get Charged Twice

Networks fail. Phones go offline. Apps crash right after you hit pay and before the server responds. When the app retries, how does the system know it already processed the request?

It uses idempotency keys.

Every payment request includes a unique key generated by the client. When the server receives a request, it checks if that key has been seen before.

If yes, it returns the cached result from the first attempt. No second debit. No second credit.

If no, it processes normally and stores the result against that key.

This is why you can lose network mid-payment, reopen the app, and still see the correct outcome. The system did not process it twice. It recognized the retry and returned what it already knew.

Why All Apps Feel the Same: The Real Breakdown

Here is the actual latency breakdown of a UPI transaction:

text
1App to PSP backend:     ~100ms
2PSP to NPCI:            ~200ms
3NPCI to bank (debit):   ~300-800ms
4Bank to NPCI (confirm):  part of above
5NPCI to receiver bank:  ~300-800ms

The dominant cost is always the bank processing time. Everything else is noise.

Google Pay can optimize its app. PhonePe can run faster servers. But neither of them controls the core banking system on the other side. Those systems respond when they respond.

So all UPI apps feel the same because all UPI apps are waiting for the same thing: the banks.

The Part That Prevents the System from Going Bankrupt

One thing that rarely gets talked about is how the ledger works.

When a UPI transaction completes, the system does not just flip a status field from PENDING to SUCCESS. It creates two immutable entries:

  • DEBIT from Alice's account for ₹100
  • CREDIT to Bob's account for ₹100

These entries are never modified. Never deleted. They are appended to an append-only ledger.

If there is ever a dispute, a reconciliation issue, or a system failure, the ledger is the source of truth. Not the cached balance. Not a status column. The actual entries.

Your balance is not stored as a number that gets updated. It is derived by summing all your ledger entries. The balance you see is a computed view over immutable data.

This design makes the system auditable by default. Every rupee can be traced to a specific event with a specific timestamp.

What UPI Apps Actually Compete On

If they cannot compete on raw transaction speed, what do they compete on?

  • How fast the camera opens for QR scanning
  • How quickly the UX gets you through the payment screen
  • How well the app handles poor network conditions and retries gracefully
  • Cashback rewards and offers
  • How much you trust the app with your linked bank accounts

The backend infrastructure is largely the same because NPCI is the same. The app experience is where the real differentiation happens.

A Clean Mental Model

If you want to explain UPI in one sentence to someone who builds software:

UPI is a thin routing layer sitting between PSP apps and banks, using an in-memory VPA registry for fast resolution, SAGA-style compensating transactions for safety, and idempotency keys to handle retries, with the actual latency determined entirely by bank core systems, not by the apps.

That one sentence contains the whole system.

Final Thought

The next time you use Google Pay and it takes two seconds, you are not waiting for Google. You are waiting for your bank's 20-year-old core system to process seven API calls across two institutions and confirm that two ledger entries have been written correctly.

The app is fast. The infrastructure is mature. The bottleneck is elsewhere.

Once you understand that, a lot of fintech architecture starts to make sense.

Bhupesh Kumar

Bhupesh Kumar

Backend engineer building scalable APIs and distributed systems with Node.js, TypeScript, and Go.