WEBVTT

00:00:15.000 --> 00:01:05.000
<v Elizabeth (Plabayo BV)> This is netstack.fm, your weekly podcast about networking, Rust and everything in between. You are listening to episode 28, recorded on the 20th of February, 2026. In this episode, we speak with Théodore Prévot creator of socketioxide a Rust library for real time systems. Web sockets give you a two-way connection, but real-time systems need more. Reconnection, hard bits and scaling. We explore how these pieces fit together in Rust. Let's begin.

00:01:05.000 --> 00:01:21.000
<v Glen (Plabayo BV)> Welcome for another week of Netstack.FM Today we will learn all about the rust crate socketioxide we have the perfect guests Is the creator and maintainer of the crate so welcome Theodore

00:01:21.000 --> 00:01:24.000
<v Théodore Prévot> Thank you, nice to meet you.

00:01:24.000 --> 00:01:46.000
<v Glen (Plabayo BV)> Yeah, so welcome very much and your live talking to us from Paris is not too far from where we are based and I'm very happy that you could make it. So as tradition goes, we would first like to get to know you a bit better. Could you tell a bit where you come from, like how you came to get into computers, networking, etc.?

00:01:46.000 --> 00:09:52.000
<v Théodore Prévot> So I started having some interest into computers in high school even before but it was more about tweaking computers ⁓ and disassembling them and cannibalizing computers. Later I got more into programming and ⁓ I discovered the whole world when doing that and I was really pleased by all the possibilities that you could have while programming so I started doing here trying to do really hard things like I wanted to do viruses in C++ and later I got more into web development, web programming I made some applications web applications and also Android applications I was quite... it was really nice and comfortable and cool to see the results on of what I built directly being used by people even if it was a limited number of ⁓ persons and I decided to continue in this path in the meantime I went to an engineering school in Paris and I met really inspiring people over there and thanks to them I continued even more in this path and so how did I from there how did I went into Rust programming? It was in 2021 I think I read a study about what were the most ecologic and economic languages it was, I don't remember the source of the study but the result was that the top languages were C obviously and C++ and Rust and some others and I was really intrigued because I had never see any mention of Rust before, I didn't know the language and the only thing I remember it was that that was ⁓ C and C++ were really hard languages that I had that I couldn't master especially when I started to do programming in high school so I digged a bit and found all the benefits that everyone said about Rust, memory safety, performances... the fact that the type system is really strict so it forces you to make correct programs and to enforce a lot of invariants at compile time etc etc and so at that time I was developing ⁓ an application for a friend who is a writer and it was a bit like Notion but more towards writing and experimenting new ideas about writing and it was completely synchronized a bit like Google Doc with the backend and the goal was to support multi-editing it used it was in full typescripts angular for the front end and node.js for the back end and I told myself that it would be really interesting to migrate the backend to Rust in order to learn Rust because I was really really interested by this language and that's how I started to work in Rust and I discovered quite fast that socket.io was not available in Rust at least for the server implementation there is a client implementation that exists and that was existing at the moment I worked on this So my whole application was using socket.io through the official library and I told myself that maybe I could ⁓ try to write a socket I.O. implementation in Rust for the server side but I started for the challenge because I wanted to learn ⁓ Rust and learn new things and also I wanted to go towards system programming I started this project I didn't expect much I even didn't doubt about ⁓ finishing it and having a working implementation one day and I worked really hard I learned a lot of things thanks to this project in Rust some maybe six months later after the beginning of the projects ⁓ I started to have a basic, really basic implementation of ⁓ engine.io it is the underlying library that socket.io is built upon and at that time some contributor ⁓ came and were really interested by the project so it really motivated me a lot keep working on it and for the two last years of my engineering school I spent a lot of time building socket.io and I think the best way to learn how to do this kind of libraries is to go check the source code of other libraries I I read the entire Tokio library for example or Axum or Hyper and it showed me how to implement certain patterns how to do idiomatic Rust and thanks to that I could implement them in socket.io socket.oxide and and learn things at the same time.

00:09:52.000 --> 00:10:14.000
<v Glen (Plabayo BV)> Yeah, I couldn't agree more. mean it tests your knowledge of it and any gap you have will quite quickly be clear. You also have to really think through the problem space as you need to implement it and as you're implementing it I imagine you will continually learn and improve what you thought you knew and get to know it better. yeah.

00:10:14.000 --> 00:10:49.000
<v Théodore Prévot> Yeah exactly. And it happened several times that I had to refactor the entire codebase because I just discovered a new pattern that was more fitted for the use cases I I think that one of the best benefits of Rust ⁓ is that because of the type system refactoring is not I was less afraid to refactor than with other language uses.

00:10:49.000 --> 00:11:23.000
<v Glen (Plabayo BV)> Yeah, agreed. mean it's one of those hidden benefits of Rust and which I think is big superpower. You can endlessly refactor. And so you said that you initially were using socket.io for this application. You're writing for your writer friend and then you decided to port the server side to Rust. In the end, you actually finish the writer application?

00:11:23.000 --> 00:11:43.000
<v Théodore Prévot> ⁓ That's a good question. No, I didn't finished it. So it is still in TypeScript and I never touched it. And I don't think I would have the time to migrate it in Rust. But yeah, quite funny.

00:11:43.000 --> 00:12:27.000
<v Glen (Plabayo BV)> Yeah, I can understand. Yeah, I mean, it's almost a cliche. Like we often get into these projects and for that project, we want to build our tooling or we want to build our underlying library. And in the end, we are just building the library or the framework or the engine and we don't get to finish the project. But we have more fun than we ever imagined. And what we produce might even create more value than the original application might ever give. I imagine that example socketioxide is now powering a lot of applications which is almost like a multiplier of what you could have done I guess with your own application.

00:12:27.000 --> 00:13:02.000
<v Théodore Prévot> Exactly, the thing that is really stimulating me and that push me to continue working on socketioxide is going on github and checking the dependent tab and going to check all the dependent projects that rely on socketioxide I love checking what they are doing at least for the open source public repository and I love the feeling of powering so many projects.

00:13:02.000 --> 00:13:33.000
<v Glen (Plabayo BV)> Yeah, good information. And so... I wonder how many people know even about socket IO and apparently socket IO is driven by engine IO. And as far as I know, engine IO is by default on top of web socket, but it can also fall back to regular HTTP polling. And I guess the client will then just send regular HTTP requests. Like can we maybe start and unpack a bit what is engine IO and is that the lowest layer? of socket I.O.

00:13:33.000 --> 00:15:31.000
<v Théodore Prévot> Yeah, it's basically that Engine.io is almost only usable through socket.io I mean people can use it independently but there is not much to build only with Engine.io and so the whole project socket.io started when WebSocket support for web browser was not really standardized and people still wanted to do server-side communication, broadcasting and real-time communication with different webpages and different users and so I don't remember his name but creator of socket.io decided to build this and it became a standard especially in the JavaScript community A lot of JavaScript developers know socket.io But it's really, it's kind of a high-level thing that have changed a lot ⁓ from the beginning of the project where the goal was only to support multi ⁓ every ⁓ browser, it was kind of a polyfill ⁓ for WebSocket ⁓ to the current state of socket.io now where there are a lot of things built upon like ⁓ multi node state communication, DOM spacing ⁓ middlewares, broadcasting, etc.

00:15:31.000 --> 00:16:23.000
<v Glen (Plabayo BV)> the authors of socket.io they also acknowledge that okay websocket themselves they're pretty cool as they are like they allow you to send dynamically messages bidirectionally but they also mention okay if you want to develop like a real-time application then you do need some layers on top the http long polling as a fallback is one thing but they also mention automatic reconnection also acknowledgement of messages maybe broadcast if you have like multiple ⁓ connected clients scaling to multiple servers and then connection recovery that seems to be the things that they mention ⁓ have needing to add on top of WebSocket if you want to make production scale applications with WebSockets does that sound about right to you?

00:16:23.000 --> 00:17:05.000
<v Théodore Prévot> Yeah, yeah, completely. But I would say that currently the protocol ⁓ suffers a bit from ⁓ its past and that things are made to be compatible ⁓ with long polling and web sockets. And I think we could have a much better protocol that would allow for faster implementations ⁓ if it was only relying upon web sockets

00:17:05.000 --> 00:17:16.000
<v Glen (Plabayo BV)> Yes, I imagine that. mean, you have users that still have this fallback to HTTP long polling Is it still even being used as far as you know?

00:17:16.000 --> 00:17:41.000
<v Théodore Prévot> I don't really know seen one issue on my project related to long polling but check dependent repositories they always... I mean they don't care about... the fallback and most of the time it will always be websockets.

00:17:41.000 --> 00:18:14.000
<v Glen (Plabayo BV)> Okay, and yeah, I was a bit surprised to read the automatic reconnection. I I'm not surprised in that, like I know that the client is not reconnecting, like let's say using it from the web API, but if we compare it, for example, to the server-side client, no, actually. Now I'm confused with Datastar I'm not sure if the server-side event client is also reconnecting or not, because I only now recall that Datastar, which is like a front-end library, they implement ⁓ server-side events on the client side themselves, because they were not happy with the server-side event client that's in the Web API. And I know the one of Datastar does do reconnection, but now I'm not sure.

00:18:14.000 --> 00:18:30.000
<v Théodore Prévot> ⁓ Mm-hmm.

00:18:30.000 --> 00:18:33.000
<v Glen (Plabayo BV)> if the default client does it or not.

00:18:33.000 --> 00:19:08.000
<v Théodore Prévot> I'm not sure but it would be surprising that it does automatic reconnection because as far as I know it's just a form of like long-lived connection so it would have to, if it's client-side it would have to handle the reconnection and make ⁓ new, initialize new server-side connections and I think that's something that is built only in the browser so

00:19:08.000 --> 00:19:30.000
<v Glen (Plabayo BV)> Yeah, yeah, I know. So that must be something Datastar specific. And then if we look at the acknowledgements, do I just see that as simple as, okay, there is just a standard format of something that is sending, I guess, text message back? Is it, is it by the way? Do they use a text frame or do they use the binary frames of WebSocket?

00:19:30.000 --> 00:20:00.000
<v Théodore Prévot> So there are multiple parsers, the most common is text, it's a mix of JSON and custom format and there is also a msgack parser that is fully binary. There are also some others they are not supported with socketioxide

00:20:00.000 --> 00:20:08.000
<v Glen (Plabayo BV)> Okay, but I imagine given the web world, I would think that the text-based one is the most common one, with it and the custom format with JSON. And so why is the custom format needed on top of JSON?

00:20:08.000 --> 00:20:48.000
<v Théodore Prévot> Exactly. I don't know because that's more part of the protocol. What I can guess is because like that we can route the JSON message specified by the user before decoding it because the the discriminant to route the payloads through the appropriate user definable is defined before the JSON payload.

00:20:48.000 --> 00:21:05.000
<v Glen (Plabayo BV)> Okay, and the broadcasting, do I just see that as it's just the server has some way to manage or group clients and it's just ⁓ resending messages from one client to all the other clients or is it something more clever going on there? ⁓

00:21:05.000 --> 00:21:37.000
<v Théodore Prévot> It is exactly that but there is some possibilities to scope broadcasting, there is a notion of room and sockets can join rooms and you can broadcast to only a specific set of rooms and exclude other rooms like you can have a whole bunch of operators to filter and broadcast to only a specific subset of circuits.

00:21:37.000 --> 00:21:47.000
<v Glen (Plabayo BV)> And given that they call it rooms instead of something like a channel, that because initially most the typical use case was like a chat server or because here it's a... Yeah, okay. And then it can also scale up to multiple instances of a server. Like how does that work? Like what does that even mean?

00:21:47.000 --> 00:23:00.000
<v Théodore Prévot> I think so, So it is done through adapters because of the rooms and there is a state on the server side so if you have a state on the server side it becomes quite hard to horizontally scale your application because you need to share the state and this is done through adapters and through another ⁓ system like ⁓ there is a Redis adapter that is the most common and there is also MongoDB, Kafka and other systems as long as the system supports some kind of pub-subchannel or stream-based communication The different server nodes can emit data through the adapters to other servers.

00:23:00.000 --> 00:23:09.000
<v Glen (Plabayo BV)> Okay, so I suppose there is some kind of high level protocol and you can implement it for whatever database backend you want.

00:23:09.000 --> 00:24:30.000
<v Théodore Prévot> Actually the protocols are different each time for each adapters, they are custom and also I make the choice to implement to make my own data formats rather than re-implementing the official protocol because for multiple reasons First because the protocols were actually not specified nowhere except from the code so I had to reverse engineer the whole implementation in Node.js That was the first reason And the other reason is that with some other formats I could improve the performance by a lot The only drawback that I see is that you can mix socket.io servers in Node.js with socket.io servers in Rust whereas if I had supported the same protocol it would have been possible but I think the use case is quite rare, seldom

00:24:30.000 --> 00:24:47.000
<v Glen (Plabayo BV)> Okay, yeah, and of course once we have this for horizontal scaling it's also not hard to imagine how you're going to do connection recovery because that's basically the similar scenario as starting a new server I suppose.

00:24:47.000 --> 00:25:51.000
<v Théodore Prévot> So connection with those two kind of connection recovery so that is recovery from the client side in this case in a case of multi node application when the client is disconnecting the server is going to store the state of the sockets on the through the adapter and like that when the socket will reconnect any other server can resume the socket state and the client state so this is the first thing and so yeah also because of the multi node application every node is fault tolerant so you can have a server that that fall down and reconnect and it will still work.

00:25:51.000 --> 00:26:04.000
<v Glen (Plabayo BV)> very cool and so all of that is socket IO but we also know by now that socket IO is actually like in two layers you have socket IO itself and you have engine IO I want to try to

00:26:04.000 --> 00:26:08.000
<v Théodore Prévot> This is... This is...

00:26:08.000 --> 00:26:34.000
<v Glen (Plabayo BV)> figure out a bit Where is the boundary? what does because we okay one layer we have? The lowest layer is let's say web socket and for now maybe we can make web socket or Like HTTP polling, but I mean basically is HTTP or or web socket. That's the lowest layer with us below this project So on top of that is engine IO. What what does engine IO add on top of that?

00:26:34.000 --> 00:26:58.000
<v Théodore Prévot> So the only other thing that is in NGINIO is ⁓ a kind of socket representation that is an abstraction of the actual transport, so as you said web socket or long polling and that's all.

00:26:58.000 --> 00:27:17.000
<v Glen (Plabayo BV)> And does that mean that given the world didn't stand still, new protocols get invented and so we got ⁓ QUIC and on top of QUIC is Web Transport? Does that mean that Engine.io can use that same abstraction also for something like Web Transport? ⁓

00:27:17.000 --> 00:27:46.000
<v Théodore Prévot> Exactly, yes, there is work on the official JavaScript implementation to ⁓ to support web transport. It was also a request on my own projects but I want to wait for Hyper to support HTTP 3 and later to implement this through the correct abstraction because currently there are some implementations in Rust but

00:27:46.000 --> 00:27:55.000
<v Glen (Plabayo BV)> Okay.

00:27:55.000 --> 00:28:05.000
<v Théodore Prévot> I do not integrate with the HTTP ecosystem and I don't want to break this whole API compatibility.

00:28:05.000 --> 00:28:09.000
<v Glen (Plabayo BV)> you mean the entire HTTP crate and its types? Is that something that like, regardless of the web framework that you support, you expect that they use the HTTP crate and those kind of family of crates?

00:28:09.000 --> 00:28:33.000
<v Théodore Prévot> hehe So yes, socketioxide can be integrated with any web framework as long as it supports tower and tower types.

00:28:33.000 --> 00:29:49.000
<v Glen (Plabayo BV)> Okay, okay, okay, very good. And so of course we... We had several episodes in NasTech.fm where we talked about Hyper and Tower. For example, episode 2 we talked with Sean McCarter, the developer of Hyper. And we also had in episode 5, we talked with Carl Lerche from Tokio where we also mentioned a bit about the history of Tower. And then we also had Lucio Franco from GRPC in episode 9, where we of course talked about Tonic and we're also tower and hyper etc was was being discussed so I would refer our listeners to those episodes if they want to learn more about hype and tower now a question about socketioxide or socketioxide ⁓ given the fact that engine IO is an abstraction does that mean that it is something like a trait in in in yours ⁓ framework or your library and you could also implement it like on top of any kind of transport protocol, let's say just pure TCP sockets or it's not as simple as that.

00:29:49.000 --> 00:30:25.000
<v Théodore Prévot> So the abstraction is not done through a trait it is done through Tokio channels. The main reason why is that especially for long polling ⁓ there is a need for a kind of channel communication and so there is not really this need for WebSocket because the WebSocket client... sorry. websocket server that I use tokyo tungstenite with tokyo tungstenite I don't know how to say and so they themselves have an internal channel but yeah so the abstraction is done through a tokyo channel

00:30:25.000 --> 00:30:49.000
<v Glen (Plabayo BV)> you Okay, but that would be then a Tokio channel over a Tokio channel because engine.io is an abstraction on top of WebSocket or HTTP polling, right? So does it mean that you are piping channels or how it works?

00:30:49.000 --> 00:31:22.000
<v Théodore Prévot> Mm-hmm. ⁓ Basically yes, I explored this piping thing a bit and at the end because I needed a lot of control over the channel I had to make to spawn a task to pipe the data between one receiver to one emitter so I couldn't pipe them directly

00:31:22.000 --> 00:31:49.000
<v Glen (Plabayo BV)> Okay, and so given, okay, we have now engine.io, then on top of that is socket.io, and as far as I understand, that one adds then things like your ⁓ namespacing, your data format, your acknowledgements, I guess some kind of metadata messages, and... That kind of thing? Is that what Soca.io is adding on top of Engine.io?

00:31:49.000 --> 00:32:23.000
<v Théodore Prévot> Mm-hmm. Yes, exactly. Just to add something, I forgot to say that NGINIO also supports Herdbit and this is through that that the server can detect if a is... if a client is ⁓ offline especially with long pulling because you don't know when was the last time that... their client was connected.

00:32:23.000 --> 00:32:31.000
<v Glen (Plabayo BV)> Okay and something like WebSocket has ping pong messages is that just what it's using for that or?

00:32:31.000 --> 00:32:40.000
<v Théodore Prévot> No it's actually... that's actually ⁓ the heartbeat over a web socket. It is...

00:32:40.000 --> 00:32:46.000
<v Glen (Plabayo BV)> Okay, so just like a regular message basically but then within your exchange protocol.

00:32:46.000 --> 00:33:10.000
<v Théodore Prévot> It is an example of why I was saying that the current protocol because it was built ⁓ originally for long polling now it suffers a bit from this past and it could be more optimized

00:33:10.000 --> 00:33:31.000
<v Glen (Plabayo BV)> Okay, fair enough. But then again, I guess it does make sense that you want to do it on top because you might not, mean, yeah, I mean, I think for most WebSocket libraries out there, you anyway, I don't think you can have access to the ping pong thing. So I guess you would anyway have to add something on top.

00:33:31.000 --> 00:34:13.000
<v Théodore Prévot> And to answer your initial question about socket IOS What do we have in socket IOS? ⁓ The basic features are ⁓ rooms and namespaces They act both as ⁓ a kind of namespacing we could say multiplexing thanks to that a connection can ⁓ share multiple handlers and we can add middlewares on top of Namespaces to authorize connections or not

00:34:13.000 --> 00:34:24.000
<v Glen (Plabayo BV)> Okay, so that's kind of like a tower layer which would add something which you do it for a specific namespace or room. Is the namespace and a room by the way the same or is it a layer on top of a layer?

00:34:24.000 --> 00:35:08.000
<v Théodore Prévot> Exactly. No, there are two layers. It makes two layers of multiplexing. So this is the first thing and after that there is obviously acknowledgement so basically there is an AckID counter I don't remember if it's server side or client side but the client can make a request and wait for an acknowledgement and the inverse is also possible, the opposite. And it's even possible on two broadcasts with acknowledgements.

00:35:08.000 --> 00:35:38.000
<v Glen (Plabayo BV)> Okay, very cool. yeah, I can see this encoding and it's indeed some kind of custom format on top of JSON. I mean, I've seen this in the the wild a lot while proxying traffic or needing to intercept or route or modify traffic and... It sometimes boggled my mind like what is this weird format but now I get flashbacks to those times.

00:35:38.000 --> 00:39:37.000
<v Théodore Prévot> And it was one of my biggest challenge and ⁓ to be honest I'm kind of proud of the results was to ⁓ deserialize this kind of data, of custom data formats in a lazy way And so I made a little tech article that you can check on my github blog about ⁓ building a custom JSON deserializer around the standard JSON deserializer and why was it needed? It is because actually to route the packets even though maybe the initial purpose of this custom format was to be able to route the packet without decentralization at the end we still have to do some part of decentralization because the event name that allows to route the packet is encoded at the first value of a JSON array and the initial implementation was relying of a dynamic decentralization with such a JSON value and it wasn't much performant because even with really high volume with a high payload it would deserialize everything and allocate everything dynamically. That was the first issue. The other issue was that the JSON payload contains placeholders where the client actually sends a binary ⁓ object and socket.io is replacing the binary object with a of placeholder and it sends the binary object adjacently to the initial JSON payload. And to integrate this dynamically in Rust and integrate this with the type system it was kind of hard and at the beginning it was quite complicated and the last issue was that in JavaScript you can ⁓ emit multiple values and they would be encoded as arrays and on the right side so if you it would be an issue because you couldn't differentiate ⁓ vector data from a tuple and there was a need to make this differentiation so for all of this reason I wanted to to make this this decelerator a rubber and so the article explains bits about the different solutions that were possible and how did I go through the process of resolving those issues through digging and digging and digging through Serde so I think I'm a bit more... ⁓ with Serde but at the beginning it was really hard I think the Serde bar is really hard when you want to implement ⁓ Deserializer yourself

00:39:37.000 --> 00:40:02.000
<v Glen (Plabayo BV)> Yeah, I mean, it's definitely something you have to read through. mean, by now there are also pretty nice unpacking videos. For example, John has a video on a de-crusting serde I think. And I think they even put it on the official documentation, but I imagine that that is from after you had to implement yourself. I don't think you had those resources available to you.

00:40:02.000 --> 00:40:54.000
<v Théodore Prévot> Maybe yes but the main issue I had is because there's a lot of documentation about how to implement your Deserializer given that you made a parser yourself but there's nothing that shows you how to make a decalizer wrapper and I had a hard time to find a similar implementation I think I found some things like to track positions while deserializing through the entire deserialization tree but it was the only crate that I found that implemented this kind of patterns

00:40:54.000 --> 00:41:21.000
<v Glen (Plabayo BV)> okay and so another thing that is noticeable when I go through the socket IO documentation is that there were some several major versions you had like the initial version and you'd be wrong V2 V3 V4 which I think is a current version like how do you deal with this socket IO versioning ⁓ from a socketioxide crate

00:41:21.000 --> 00:42:16.000
<v Théodore Prévot> protocol versioning is there are multiple protocol versions. There is, I don't remember if it's v5 or v4 but I only support the current socket.IO protocol is v5 and there is a previous one on v4 the changes are quite small between them and so the previous ⁓ protocol version can be enabled with a feature flag and in this case it will ⁓ it will allow you to accept previous protocol client with the little configuration

00:42:16.000 --> 00:42:40.000
<v Glen (Plabayo BV)> Okay, that's good to know. And I don't really see this. I saw at some point this V4, V5, but then I'm confused with what is the difference then with the version that you see also on the website itself, like this V4X, V4 3X, V4 2X. Is that like, we had another version of something else?

00:42:40.000 --> 00:43:34.000
<v Théodore Prévot> It's kind of hard because there are three things, there is ⁓ the socket.io protocol version, there is the socket.io JavaScript implementation version, there is the njan.io protocol version and the njan.io official implementation version. what interests Us is only the protocol versions and the socket.io protocol versions are v5 and v4 and the v5 is based on engine.io v4 and the v4 is based on engine.io ⁓ v3 found much people who used version.

00:43:34.000 --> 00:44:30.000
<v Glen (Plabayo BV)> good to know and then yeah I wonder a bit like where do you put your abstraction because I mean in one okay you have the engine IO abstraction you have the socket.IO abstraction but to me you could almost certainly see them like separate from your ⁓ underlying HTTP or web sockets ⁓ yeah library implementation because in in a way they they shouldn't really matter but as far as i know you are quite strongly bound to your web socket library and your ⁓ yeah htp ecosystem etc was there like a yeah what would be the reasons behind that was it just because that's what was easiest at that time or was there also like a reason why you couldn't make that more decoupled

00:44:30.000 --> 00:46:36.000
<v Théodore Prévot> So initially it was because that was much easier and that I was mostly focused about building something working and later I think about it so there are multiple kind of dependencies that why it would be nice to have a better abstraction the first thing is the async runtime currently it uses tokyo and so it would be possible to support to support something else but as there is also ⁓ strong dependencies on HTTP, Tower etc this is a whole ecosystem that is tightly bound to Tokio so I would need to have an abstraction for the whole dependencies this is the first reason another one is that I don't think there is much usage the burden of maintaining all those abstractions would be compensated by the number of users I think no one except no one asked me for abstractions and dependencies except from you for the integration with Rama but this is a whole kind of ⁓ new complexity because building a library that is that is fully asynchronous and making it asynchronous is kind of hard. There is a lot of interesting patterns to explore, especially around Sans-IO I don't know if you heard about this.

00:46:36.000 --> 00:46:45.000
<v Glen (Plabayo BV)> Yes, we had an episode with ⁓ Martin Algestan He is the developer and maintainer of, So he also has uReq which is like an HTTP client, I think. And so we had an entire episode about the Sans IO pattern. And yeah, I like it a lot for sure. It helps a lot in this kind of ⁓ frameworks or libraries.

00:46:45.000 --> 00:47:37.000
<v Théodore Prévot> Mm-hmm. and so a little challenge that was to try to implement engine.io in C with the sans.io pattern it's a whole new complexity compared to Rust especially because I need some time some type of custom async runtime to be able to make heartbeat working

00:47:37.000 --> 00:49:03.000
<v Glen (Plabayo BV)> Yeah, mean, doing it also a million CS is definitely like the different than doing the inverse. and yeah i mean but but it does help a lot because like you can just test it decoupled from from your actual i-o layer because that's what sonio is about it's about making sure okay you focus on your protocol and for example you make you set yourself you make use of a tungsten and as far as i know they also implement in in in a sonio way where they don't really care so much about the underlying your protocol it's more you just have something that implements the protocol so in that case WebSocket and then underneath it you have something that provides you with a byte stream but you don't really care so much where that comes from it could be just an in-memory byte stream it could be a TCP it could be whatever like as long as it works and then of course on top of that you would have like the HTTP handshake but that's kind of like ⁓ separate detail because those really matter and that also happens before WebSocket. It also happens before Socket.io I imagine. Or do you do something special with HTTP and Shake, do have couple of custom headers in Socket.io?

00:49:03.000 --> 00:51:23.000
<v Théodore Prévot> No, there is no custom headers, are parameters extracted from the query params but nothing more. on statically on this dependency lower the complexity bar by a lot and there are a lot of things that I want to work on and higher level things that I think that are really really wanted by the community and So I think it's more a priority compared to abstraction Also, I would add that The user base of socketioxide is more There is a lot of rust newcomers exactly like myself when I started socket.io The main reason why is that people know socket.io they have implemented it and they have used this story in JavaScript and they come to Rust and the first thing that they say to them is ⁓ I'm going to migrate my implementation, my server, my application in Rust so they fall on my lib and they kind of start working and doing the implementation with socket-io, socketioxide and That's how they mostly get into Rust and it is really really high level compared to other protocols. It's not that performant and so there a lot of things like the need for integration testing, adapters ⁓ ease of use documentation that are much more important than actual abstractions on the network dependencies.

00:51:23.000 --> 00:51:42.000
<v Glen (Plabayo BV)> Yeah, I fully agree and I understand your point of view. But then I also see, as you mentioned yourself, you wanted a server implementation. Before that, there was already this Rust socket IO client implementation and it's still there.

00:51:42.000 --> 00:51:44.000
<v Théodore Prévot> Mm-hmm.

00:51:44.000 --> 00:52:02.000
<v Glen (Plabayo BV)> Yeah, I mean, it seems to be a bit of a death project. I mean, maybe just finished, which is also fine. But, ⁓ yeah, there seems to be like a little overlap because I imagine that the underlying protocol is pretty much the same between the client and the server. You have, of course, features which are server side only, like broadcasting. But there is a little overlap, no?

00:52:02.000 --> 00:55:55.000
<v Théodore Prévot> Bye! Of course, yes, that is an overlap. Initially I was wondering if I could try to integrate it or make a common implementation under the Rust-OK.IO project. ⁓ At the end I didn't do it, I did something on my side. ⁓ But there are lot of different... even if we... without talking about the client versus server more about the API philosophy and the ease of use etc. There are a lot of different things and so that's the reason that I didn't wanted to merge or try to merge the two... projects and for example the way we specify handlers in socket.io is completely similar to Axum so people that use Axum are really comfortable and also it avoids a lot of manual boilerplate like boxing closures and boxing features Also it implements the extractor patterns so there is never unused parameters and people can build their own extractors to do custom behavior. So as you said the socket.io client is currently a I don't really know how much the creator invested his time and so I was thinking about making a client implementation on with socketioxide and the main reason is not really to like for concurrency reason I don't think there is the need for we don't need to fight each other especially in the open source world it's more because a lot of people ask me for testing and end-to-end testing be to have a client socket aux feed that share the same base type through a core library and thanks to that the the people could make their tests and this would go through the whole tower abstraction without needed networking When you test, when you're doing, making integration test with Axum, you are sending HTTP requests through, often through Tower because an Axum router implements a Tower service so you can just call one-shots and make your... and make handcraft an HTTP request and because they are the same base types the integration testing is really really easy and I would like to have the same experience with socketioxide

00:55:55.000 --> 00:56:08.000
<v Glen (Plabayo BV)> Yeah, yeah, I understand. So how do you currently do your integration test? you actually just open transport layers and work with the Rust socket IO client implementation or?

00:56:08.000 --> 00:57:04.000
<v Théodore Prévot> So, ⁓ Inside the library I'm doing a lot of different types of testing Integration tests are made by manually crafting the message types and accessing some internal implementation so for the project needs it's okay but it is absolutely not usable and ready for ⁓ main users and also there are end-to-end testing there is a test suite that been made by the official maintainer of ⁓ the socket.io protocol is testing everything and that assure that the protocol is respected.

00:57:04.000 --> 00:57:19.000
<v Glen (Plabayo BV)> yeah, given all this, what is kind of the future for socketioxide besides the client implementation that you might want to do? Like what's on the roadmap and what are your priorities a bit?

00:57:19.000 --> 00:59:30.000
<v Théodore Prévot> So, what's on the roadmap, I would say first, ⁓ support for other kind of adapters. Currently there is only MongoDB and Redis. I have started ⁓ post-reimplementation that I'm working on. There is also, as we said, the client and... I started with kind of high objectives because ⁓ client implementation should be less complex and so I wanted to be runtime async mostly by using only manually defined features and manually defined streams. I don't know if it will be possible but it's something that I'm exploring and if it's too hard or that is not possible I will fall back on doing a more classic implementation. But I think it's really important to have this async runtime abstraction because Clients might be used in WebAssembly for example and in WebAssembly you won't going to include the whole Tokio runtime so that's a first example you might want to use these clients in embedded systems it would be a bit weird but why not and so because of that i want to focus on this fully async runtime abstraction

00:59:30.000 --> 01:00:24.000
<v Glen (Plabayo BV)> No, very brave of you. It's definitely, depending on how complex your library is, it's certainly not an easy feat in the current version of Rust, I would say. Like I tried, for example, at the beginning to make Rama runtime agnostic and... Yeah, it quite quickly got very painful. know Hyper did succeed, but it does make things a lot more awkward over there, I feel. Like you have lot of obstructions over little simple things. And next to that, I also discovered that Tokio, I discovered over the years that Tokio is a lot more powerful than I gave it credit for. you can run it on embedded systems, you can... I think you can, depending on what tier of app assembly you want, think you can use Tokio as well.

01:00:24.000 --> 01:00:28.000
<v Théodore Prévot> Yes, it does WebAssembly compatibility.

01:00:28.000 --> 01:01:21.000
<v Glen (Plabayo BV)> yeah so and and another reason i wanted it for is okay what if you want to run a runtime per thread but even that you can do with tokyo so Yeah, all the reasons I had initially to make this ⁓ agnostic possible, kind of like, yeah, I removed the reasons one by one and I didn't find so much reason anymore to go through all the efforts. That said, the scope of Rama is like a lot bigger than so-called socketioxide. So I think in your case it might be possible, but still, I wonder how much request there really is for because I I imagine the typical Axiom user, most of the, yeah, I guess, yeah, I don't think they really anyway care about something that's not Tokio.

01:01:21.000 --> 01:01:28.000
<v Théodore Prévot> No, I think it's also more of a challenge for me. they want to explore.

01:01:28.000 --> 01:01:50.000
<v Glen (Plabayo BV)> Okay, yeah, I mean, I think it's cool anyway. then another question I have is like, okay, initially you develop this with this interest and you manage to keep this interest over the years. You also manage to keep working with over the years. Is this something you can do as part of your job or is it like purely a free time project?

01:01:50.000 --> 01:02:57.000
<v Théodore Prévot> It is purely a free time project and currently these last months it became quite hard to take time because I have quite challenging work in rest also and because of that it's hard to find free time. It's not especially about having the time It's more about having time, having space to allow thinking about the architecture and the organization and how am I going to fulfill this feature to... All of that is being a bit replaced by my work that is almost... as challenging as this implementation of socketioxide so yeah a bit hard for me

01:02:57.000 --> 01:03:12.000
<v Glen (Plabayo BV)> How do you see that I'm being sustainable? it just because it's so interesting to you that you keep finding time to work on it or how do you keep yourself motivated to keep working on this?

01:03:12.000 --> 01:03:14.000
<v Théodore Prévot> on socketioxide ⁓ it's mostly because the fact to contribute to open source it's really really important for me and I love the philosophy behind this as I said at the beginning of the podcast it's really really important for me and it brings me a lot of joy and

01:03:14.000 --> 01:03:41.000
<v Glen (Plabayo BV)> Yes.

01:03:41.000 --> 01:04:04.000
<v Théodore Prévot> to just go to the dependence tab and see what everyone is building with Socketoxid and it makes me really happy and it gives me the motivation to continue even if it's really really slowly because I don't have much time.

01:04:04.000 --> 01:04:50.000
<v Glen (Plabayo BV)> it. In that case I covered everything that I wanted to. ⁓ cover about Soca Dioxide. would encourage people to explore the product, it's quite a cool one. That said, I imagine that anybody interested in Socket.IO and is also into rust, they probably already discovered your project, so I don't think they need the extra shout-out. But anyway, think it deserves a spotlight and I'm very grateful for the work you put into it. Is there anything else that you think we didn't discuss about the project? or the underlying projects which you would like to highlight.

01:04:50.000 --> 01:04:57.000
<v Théodore Prévot> No, I think I don't have any other ideas.

01:04:57.000 --> 01:05:22.000
<v Glen (Plabayo BV)> as fair enough. We already discussed about quite a lot and so I wish you like a pleasant 2026 like we're already almost end of February so I guess you are already past the new year's resolutions but regardless I hope it's a year that's good for you and for the project and I wish you the best of luck with it

01:05:22.000 --> 01:05:26.000
<v Théodore Prévot> Thank you.

01:05:26.000 --> 01:05:31.000
<v Elizabeth (Plabayo)> Netstack.fm is brought to you by Plabayo building secure, open, and resilient infrastructure with Rust protocols, and purpose. This show is also made possible by Rama, the open source networking framework. Plabayo offers service contracts and welcome sponsorships to keep building and supporting its ecosystem. The theme music of this podcast was composed by DJ Mailbox. If you enjoyed this episode, don't forget to subscribe on your favorite podcast platform and leave a five-star review. It really helps others discover the show. Thanks for tuning in. We'll see you next time for the next handshake.

