DEV Community

Haripriya V
Haripriya V

Posted on

ASSIGNMENT 36

** Building a Reliable Digital Wallet System (Like PhonePe / GPay)**

Introduction

In today’s digital world, applications like Google Pay, PhonePe, and Paytm handle millions of financial transactions every second.

Behind these simple “Pay” buttons lies a highly critical system where data consistency is everything. Even a tiny inconsistency can lead to:
•Money loss
• Duplicate transactions
• Incorrect balances

To prevent this, databases rely on ACID properties, especially Isolation, which ensures transactions don’t interfere with each other in unsafe ways.

Database Setup

We begin with a simple accounts table:

CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
balance INT NOT NULL CHECK (balance >= 0),
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Sample Data

INSERT INTO accounts (name, balance)
VALUES
('Alice', 1000),
('Bob', 500);

This simulates a wallet system where users hold balances.

Simulating Concurrent Transactions

To understand how isolation works, we simulate two concurrent database sessions.

Scenario: Two Transactions on Same Account

Session 1 (T1)

`BEGIN;

UPDATE accounts
SET balance = balance - 800
WHERE name = 'Alice';`

Alice’s balance becomes 200 (but uncommitted)

Session 2 (T2)

`BEGIN;

SELECT balance FROM accounts WHERE name = 'Alice'; `

Now the key question:
Can T2 see the updated balance (200)? Or still 1000?

This depends on the isolation level.

Isolation Levels Explained

Read Uncommitted

Lowest isolation (rarely used in PostgreSQL)
•T2 can see uncommitted data
•Leads to Dirty Reads

Problem

T2 might see balance = 200 even if T1 later rolls back.

Result: Incorrect financial state

Read Committed (Default in PostgreSQL)**
•T2 cannot see uncommitted changes
•Only committed data is visible

✔ Behavior

T2 sees:

Alice = 1000

Issue: Non-repeatable Reads

If T1 commits later, T2 may see different values in the same transaction.

Repeatable Read

•Ensures consistent snapshot during transaction

✔ Behavior
•T2 always sees 1000 during its transaction
•Even if T1 commits later

Issue: Phantom reads still possible (in some DBs)

Serialize (Highest Isolation)

Most strict and safest
•Transactions behave as if executed one after another

✔ Behavior
•Prevents:
•Dirty reads
•Non-repeatable reads
•Lost updates

Example Outcome

One transaction may fail with:

ERROR: could not serialize access due to concurrent update

You must retry the transaction

Key Problems Demonstrated

Dirty Read

Reading uncommitted data → leads to wrong balance

Non-Repeatable Read

Same query returns different results within a transaction

Lost Update

`-- T1 reads 1000
-- T2 reads 1000

-- T1 updates to 200
-- T2 updates to 300

-- Final = 300 (T1 lost) `

Two transactions overwrite each other’s updates

Example:

Why Isolation Matters in Wallet Systems

In a real-world wallet:
•Multiple users may send money simultaneously
•Systems must prevent:
•Double spending
•Balance corruption
•Race conditions

Without isolation, financial systems would be unreliable.

Best Practices for Wallet Systems

SELECT * FROM accounts
WHERE name = 'Alice'
FOR UPDATE;

•Use Serializable isolation for critical transactions
•Use row-level locking:

Implement retry logic for failed transactions
•Keep transactions short and efficient

Conclusion

Building a digital wallet system is not just about transferring money—it’s about guaranteeing correctness under concurrency.

Through this experiment, we observed how different isolation levels impact:
•Data visibility
•Transaction safety
•System reliability

Top comments (0)