Divyansh GuptaDivyansh Gupta
All work
Mobile · Realtime · WebRTC

KVCall

A calling and messaging app backed by a self-hosted WebRTC SFU and a billing ledger.

ExpoNestJSMediasoupSocket.ioRedisPrisma
KVCall interface

Overview

KVCall pairs an Expo mobile client with a NestJS backend that runs its own WebRTC SFU (mediasoup) for calls, alongside contacts, messaging, presence/status, and subscriptions. A ledger service tracks call usage against subscription plans, so billing and call history stay consistent with what actually happened on the media layer.

The challenge

Voice/video calling needs low-latency signalling and media routing that scales beyond simple peer-to-peer, while usage-based billing needs to reconcile cleanly with call events that can end abruptly (dropped connections, backgrounded apps). Both had to work together without the ledger drifting from what the SFU actually delivered.

What I built

  • React Native (Expo) client with calling, messaging, contacts, and presence/status
  • NestJS backend running a mediasoup SFU for group and 1:1 calls
  • Socket.io signalling layer with a Redis adapter for horizontal scaling
  • Subscription plans and a ledger service that records usage against them
  • Push notifications and in-app status/marquee messaging

Screenshots

KVCall screenshot 1
KVCall screenshot 2
KVCall screenshot 3
KVCall screenshot 4
KVCall screenshot 5
KVCall screenshot 6
KVCall screenshot 7
KVCall screenshot 8
KVCall screenshot 9

Architecture

Expo App
Socket.io Signalling (Redis)
Mediasoup SFU
NestJS API
PostgreSQL (Prisma)

Engineering highlights

Self-hosted SFU

Media is routed through a mediasoup SFU under our control rather than a third-party calling SDK, which keeps latency and cost predictable at scale.

Usage-linked billing

A dedicated ledger module records call usage against subscription plans, so billing reflects what the SFU logged rather than relying solely on client-reported call duration.

Scalable signalling

Socket.io with a Redis adapter lets signalling scale across multiple backend instances without pinning users to a single node.

Results

Self-hosted SFU

Media layer

Socket.io + Redis

Signalling

Calls · Ledger · Subscriptions

Core modules