How to build a pay-per-minute consultation app like Astrotalk
A personal build: the wallet sets the call length before it rings, billing settles once at the end, and here's what production would still need.
In this article7 sections
A user with $5 in their wallet calls an expert who charges $0.20 a minute. Before the phone rings, the app has to answer one question: how long can this call last? The rest of a pay-per-minute app, including the expert's payout, depends on getting that number right and settling it honestly afterwards.

- Wallet balance
- $5
- Expert's rate
- $0.20/min
- Longest affordable call
- 25 minSet before the call rings
I built a working version of this kind of app as a personal learning project, modelled on how consultation apps like Astrotalk work. It isn't affiliated with Astrotalk and it hasn't handled real customers' money. Here is how it works, where my own documentation overstated it, and what I'd add before real money flows through it.
What the app has to do#
The user journey is short:
- Browse verified experts, their rates and whether they are online.
- Top up a wallet.
- Call an expert, who sees an incoming call and accepts or rejects it.
- Talk over audio or video while a countdown shows the time left.
- End the call, pay for the minutes used and leave feedback.
Behind that, the expert needs earnings and call history, and the business needs its share of each call recorded.
Three services, each with one job#
I split the system into three parts, plus a media provider.
| Part | Built with | Job |
|---|---|---|
| Web app | Next.js | Browsing, the wallet and the in-call screen |
| API | Express, Prisma, PostgreSQL | Wallets, calls, availability and transactions: everything that must survive a restart |
| Real-time server | uWebSockets.js | Who is connected, plus ringing, accept, reject and end messages |
| Media | Agora | The audio and video itself |
The split follows the failure modes. If the real-time server restarts, connections drop and users reconnect. That's annoying. If a wallet balance or a transaction disappears, someone loses money. So the API owns every cent, and the real-time server never stores money at all.
Media goes to a provider. Reliable audio and video on Indian mobile networks is a hard problem, and providers like Agora sell a working answer to it.
The wallet sets the call length before it rings#
When a user starts a call, the API reads their wallet and bonus balance and the expert's rate per minute, then calculates the longest call they can afford. It creates the call record in a database transaction, with the expert's availability checked. With $5 and a rate of $0.20 a minute, the limit is 25 minutes, and the in-call screen counts down from there.
Charge every minute, or once at the end?#
My own README said the app had "live per-minute billing". The code settles once, when the call ends. The countdown is live; the charge isn't. I'm pointing this out because a lot of per-minute billing descriptions blur the same line, and the difference matters when something fails.
At the end of a call, the API:
- checks the call hasn't already ended or been rejected, so a repeated end signal doesn't charge twice;
- calculates the charge from the call's duration;
- deducts it from the wallet and bonus balance;
- splits the amount between the expert and the platform;
- writes transaction records for all of it.
Settling once is simple and needs one set of writes per call. Its weakness is a crash in the middle of a long call: the system then has to rebuild the duration from whatever it recorded before the crash. Debiting every minute writes more often but limits what any single failure can cost.
For a production app I'd keep settlement at the end and add checkpoints. Record the call's elapsed time every minute or so, and reconcile against the media provider's records afterwards. Either way, a production app needs metering that survives a crash.
Ending a call safely#
A call can end in several ways: the user hangs up, the expert hangs up, the money runs out, or the media provider reports the call is over. In my build, the real-time server tells the API through an internal endpoint, and Agora's webhooks are signature-checked in production before the API trusts them.
The "already ended" check handles a second end signal that arrives after the first has finished. Two arriving at exactly the same moment is a harder problem, and it's on the list below.
What breaks first at scale#
The current version runs on one real-time server. Here is what I'd change before real traffic, roughly in order:
- Connection routing. The server keeps each user's connection in memory. A second server can't ring a user connected to the first, so calls need routing between servers, for example through Redis.
- Presence that survives restarts. Who is online also lives in one process's memory. A restart forgets everyone.
- More than one device. The server holds one connection per user, so a second device replaces the first.
- Concurrent settlement. Two end signals at the same instant, or two duplicate webhooks, must still produce exactly one charge. That needs database-level protection such as a unique constraint on the settlement, never a check followed by a write.
- Reconnect and resume. A dropped network shouldn't end a paid call without a grace period.
- Load tests and monitoring. I have no load or latency measurements for this build, so I won't quote capacity.
- A security pass. The source still logs a debug token. That goes before anything else ships.
The same duplicate-payment problem appears in paid slot booking without double bookings, implemented in the MentorAID client project.
Where to start if you're building one#
Astrologers, doctors, lawyers, tutors and coaches all sell expert minutes, and a first version needs the same pieces: verified expert profiles with rates and availability, wallet top-ups through an Indian payment gateway, calls through a media provider with a visible countdown, settlement with a proper ledger, and an earnings view for experts.
Most of the scale list can wait until you have real users. The ledger and the security pass can't.
Saumya and I build booking and payment products for businesses like these. If you're planning one, send us how your experts work today and we'll tell you what the first release should include.
