ISSUE 42
Software Architecture

I Built a P2P Messenger Without a Central Message Database: Lessons in WebRTC and E2EE

An analysis of the architectural trade-offs, signaling challenges, and cryptographic complexities involved in building a decentralized P2P messenger.

Abhik Kumar Panda
Abhik Kumar Panda
Creator & Engineer
August 29, 2026 · 3 min read
Diagram illustrating a decentralized WebRTC mesh network for peer-to-peer messaging

Building a messaging application without a central database is an exercise in shifting the burden of state management from the server to the client. In a traditional architecture, the server acts as the source of truth, managing message queues, user presence, and delivery receipts. In a peer-to-peer (P2P) model, the network topology becomes dynamic, and the ‘server’ role is relegated to a lightweight signaling layer that merely facilitates the handshake between two independent clients.

The core of this implementation relies on WebRTC, a protocol designed for real-time media, which I repurposed for arbitrary data channel communication. While WebRTC provides the primitives for direct communication, it introduces significant complexity regarding session establishment and maintaining connection state in a world dominated by restrictive NATs and firewalls.

The Signaling Paradox

WebRTC requires a signaling mechanism to exchange Session Description Protocol (SDP) offers and answers. Because this signaling must occur before a P2P connection exists, a server is still necessary. However, I kept this server ‘stateless’ by utilizing a serverless architecture (AWS Lambda + DynamoDB). The server stores only the transient signaling metadata and never touches the message payload itself.

The primary challenge here is the ‘offline messaging’ problem. If Peer A sends a message while Peer B is offline, there is no central database to buffer the payload. To solve this, I implemented a ‘Store-and-Forward’ buffer in the client-side IndexedDB. When Peer B reconnects, the signaling server triggers a sync event, prompting Peer A to push the buffered encrypted blobs directly to Peer B.

End-to-End Encryption (E2EE) Implementation

Since the signaling server is effectively a black box for the data, E2EE is not just a feature; it is the baseline architecture. I utilized the Web Crypto API to handle asymmetric key exchange using X25519 for Diffie-Hellman key agreement. Each message is encrypted using AES-GCM, which provides both confidentiality and authenticity, ensuring that no man-in-the-middle can tamper with the signaling or the data channel.

async function encryptMessage(data: string, sharedKey: CryptoKey) {
  const iv = window.crypto.getRandomValues(new Uint8Array(12));
  const encoded = new TextEncoder().encode(data);
  const ciphertext = await window.crypto.subtle.encrypt(
    { name: 'AES-GCM', iv },
    sharedKey,
    encoded
  );
  return { ciphertext, iv };
}

NAT Traversal and Connectivity

WebRTC struggles in symmetric NAT environments. Without a robust STUN/TURN infrastructure, P2P connectivity fails in approximately 20% of corporate or restricted network scenarios. I deployed a fleet of coturn servers to act as relays. While this introduces a cost, it ensures that even when direct peer-to-peer connectivity is blocked, the encrypted traffic can be proxied through a TURN relay without the relay provider ever seeing the plaintext content.

Trade-offs and Limitations

  • Battery consumption: Maintaining active WebRTC data channels on mobile devices is significantly more resource-intensive than long-polling or WebSockets.
  • Device fragmentation: Browser implementations of WebRTC are mostly consistent, but handling connection drops during mobile-to-Wi-Fi network switches remains a persistent engineering headache.
  • Metadata leakage: While the content is encrypted, the signaling metadata (who is talking to whom and when) is visible to the signaling server.

Conclusion

Removing the central message database forces the engineer to treat the network as an unreliable, untrusted medium. By leveraging WebRTC for data transfer and the Web Crypto API for security, I achieved a system where the server is merely a conduit rather than a custodian of data. The trade-off is a more complex client-side codebase and a reliance on TURN relays for connectivity. For applications where privacy and autonomy are paramount, this architecture offers a robust, albeit challenging, path forward.

Share Twitter LinkedIn
Abhik Kumar Panda
CONTRIBUTING FELLOW

Abhik Kumar Panda

Creator & Engineer

Software engineer and creator passionate about technical writing, systems architecture, and AI.

Continue Reading

Stay in the loop.

Get new engineering articles, systems ideas, and things worth knowing — straight to your inbox.

No spam. Just useful things.
Unsubscribe anytime.