Design of a chat application

Hey Y’all,

I’m attempting to design a chat application that does text, voice, and video. I have messed with rust-libp2p to learn how the different protocols work but I am left with some questions about how the protocols are supposed to interact with each other and what some try to accomplish.

Peer Discovery

I plan on using MDNS to connect peers on the local network. I explicitly add them to the KAD and gossipsub protocols. Cool, easy. The question is how do I get people outside my network to discover me. I am going to have to give some piece of information to my fellow peers, but I am unable to figure out what that is precisely. Can I get away with just giving out a peer ID? My program has the KAD protocol and is bootstrapped to the bootstrap nodes but when I search for peers I only get peer IDs back, not multiaddresses. Is a peerID enough to dial a peer? I have been unable to find any information on dialing unknown peers, or peers without a known address.

So lets say I need more than just the peer ID to give to people. I see a few ways to get this out so clients know where to connect and who they are talking to:

  1. Give out a multiaddress of my client. But what happens if the address changes? Would I need to give the new one out?
  2. Put a record in the DHT and give the ID of that out. Clients would then download that record and use that information. I believe this still suffers from the above issue, if I need to change the record how do I notify peers of the update?
  3. Use gossipsub to publish the address. Clients could listen to the topic and connect to peers whos “chat rooms” they would want to join. If the peer changes an address they can publish the new one. However is it “safe” to be publishing this information to the network? I’m assuming one could write a program to read all messages on gossipsub.

Once I get the network information needed, the clients can connect and attempt hole punches as needed (which seems automatic). Now that they are connected to me, I will need to get a list of peers that they should also try to connect to. I will have to have a list of peers that are in the room and publish that, probably in a similar way to above.


Now that peers are connected, they will want to exchange messages with each other. What is the best way to do this? And what is the best way to do this securely. The two ways I see are through gossipsub like in the rust example, or writing my own stream protocol like in the js example.

Text would be a low bandwidth and “reasonable” latency requirements (I’m not worried about how fast a message gets to its peers as long as its “reasonable” to have a chat conversation). I have not been able to find any bandwidth limits or latency of gossipsub but from my reading it seems that its built for small packets, and from my experimentation once a peer starts getting messages on a topic it gets there pretty quickly. It also seems the advantage of using gossipsub is that its easy for people to join and you don’t need to handle connections between peers. However this seems to not prevent people from joining or from anyone reading messages if they know the topic. This seems out of the question for any chat application that has private rooms, but perhaps we could encrypt every message for every intended peer with their public key and then publish all those messages. The bandwidth would be multiplied by N peers but that is probably sill reasonably low just for text.

The js example writes their own stream protocol. It has to deal with dialing its own peers but I should know that already from the Peer Discovery section. Once that is set up you are not sending info to unknown peers. You probably would not need to encrypt every message since we are only sending info to known peers. However this has the issue that we can only send chat over peers that are directly connected and not to those who failed the hole punch. I would have to come up with my own routing of messages through peers to get the message to peers that are not directly connected.


Streaming voice has low bandwidth but low latency requirements. I care if there is a delay with voice. Since I have not been able to find any information on the latency requirements of gossipsub I am not sure I can use it. So I am left with writing my own stream protocol + routing as with the chat stream protocol.


Streaming video has high bandwidth and relatively low latency requirements. Gossipsub is out of the question since it cant handle high bandwidth. As above, ill have to write my own protocol to handle this scenario.


It seems it best way for libp2p to manage all the data its sending is to use multiple streams. So I would write one stream protocol for every piece of functionality instead of having one stream do everything. Is that correct? Is there any overhead for having many streams?



  1. What is the best way to publish connection information? Over gossipsub? Is there a security issue there? Can I get connection information from KAD?
  2. Should I encrypt messages and publish them over gossipsub or should I write stream protocols for every bit of functionality I need?

Have you checked out GitHub - libp2p/universal-connectivity: Realtime decentralised chat with libp2p showing ubiquitous peer-to-peer connectivity between multiple programming languages (Go, Rust, TypeScript) and runtimes (Web, native binary) using QUIC, WebRTC and WebTransport as a starting point?

I wouldn’t use gossipsub for voice/video, as there is still duplication of messages due to overlap

1 Like