skip to content

Adding state to serverless applications

with Sunil Pai

Serverless has always come with a trade-off: apps that use it are stateless by design. But Sunil Pai has a way to make serverless stateful, and he's going to show us how it works.

Topics

Transcript

Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON: What are we doing? Let me do this. Wait. What is this? What is happening? Hello, everyone, and welcome to another episode of Learn with Jason. I still don't know how all these buttons work. Today on the show I'm super-excited to bring back long-time friend of the show and friend of mine, Sunil Pai. How are you doing?

SUNIL: Doing great. It's great to see you gone.

JASON: I'm exited to have you on the show. For a lot of reasons, it's an interesting topic. And it's an interesting time right now. I know we have some big news. Why don't we let you share that, for those that aren't familiar with you and your work, who you are, what you do, and what's going on lately?

SUNIL: Hi, everybody. My name's Sunil Pai. I'm a software engineer. I spent a year on the React team, I didn't do much time there. I spent time in Oculus, that was a lot of fun. I worked in Cloudflare, and for the last year, building a startup called Partykit. With real-time experiences with a few twist, basically websocket, plus, plus. But as of a couple of weeks ago, Partykit was acquired by Cloudflare, my alma mater. Kind of a speed run for a startup. And I'm now back in Cloudflare. I'm in the Cloudflare London office right now. I'm doing orientation sessions for the second time around, which is weird. But I'm like, yeah, okay. I kind of know all of this. So, yeah, it is an interesting time for me. And a little surreal, but it's also such an interesting time in the industry to be working back in an infrastructure company kind of on the new problems that are around. And yeah. That's -- that's what I'm -- also, I think I have been on Learn with Jason twice before. I think the first time we spoke about esbuild, and last time we spoke about Partykit itself. And honestly, I had a great time then. Coming back here is just the easiest decision for me.

JASON: Yeah, it's always a good time. I love -- you are one of the people I would put in the bucket of like tech futurists. You always seem to be looking at what's next. To the point that a lot of the time I feel like I don't quite understand what you're talking about yet. And that's one of the reasons I like having you here. It's fun to talk through these ideas and try to imagine where the industry is going instead of talking about where we are today. But it's a really interesting time, as you mentioned, to be at an infrastructure company because it feels like -- I mean, I guess we can -- we can start with a little bit of the recent news. So, I think yesterday or earlier today Vercel actually did a big walk back on the edge. And was kind of saying, like, hey, we were wrong about this. It's not good for what we thought it was good for. Which kind of caught me off guard. And so, maybe we start there. Like it -- you're back at Cloudflare, which I think is the OG edge company. Do you agree with the sort of sentiment that was in that post from Vercel? About the edge?

SUNIL: One of the things I love is diving into nuance. First of all, big fan of Vercel and Cloudflare. This is not -- and this is not my -- what I'm saying right now is not the opinion of the company. Even though I think it should be. It's not an official opinion. And I think the nuance is actually fascinating.

JASON: Yes.

SUNIL: And very -- and coincidently, and I swear to whoever is watching right now. We decided this topic a few weeks ago.

JASON: We did. We decided this topic months ago.

SUNIL: Exactly. What happens was is Vercel a couple of years ago, two and a half years ago, they introduced their new edge product. Edge middleware. Which is, hey, you can write code in your Next.js app or any app. Where that code will run closest to the users that request it. previously what happens closest to the users is the CDN. That's always great. Let's be clear. Distributing like the static parts of your app, all across the world, closes to your users, just means faster website. Amazing stuff. But you should also write code closest to your users. And folks might be familiar with Cloudflare Workers which is also a technology that does exactly the same thing. Hey, it finds something incredibly close you within the range of 20, 30 milliseconds. And that's around your JavaScript that takes a request and returns a response. The problem is that like any technology it usually starts off being marketed as a panacea, as a universal solution for everything. Run your React app here, run everything. But in reality, there's a nuance to that. For the big one that we were talking about yesterday is your data is actually never going to be closest to the users. And if it is, it has its own tradeoffs. So, usually, what you is you take one data center, maybe use AWS. So, US East 1. Somewhere in New York. That's where your database is. Having your database in one place has some good qualities. The biggest one is you don't have to worry about consistency. People who make the requests to get the particular data, they get similar data because it's at the same place. The moment you have replicas of the data across the world, one thing that happens is users are closest to replicas who get data from there, it might be a little faster, but stale. Might not be replicated from the source, whatever the primary part of your database is. And the second one which is what I think Vercel are talking about is, oh, if your compute, your JavaScript, your server is running, it's close to your users. And your database is halfway across the world. And in the single request in any non-trivial application, make requests to the database. Give me the user data and the product details data. If these two are far away, that means the round trip, it has to do it multiple times and it just gets really slow. Now a solution for it might be, oh, let's push the data to all closest to the users. But it's much harder to push data like that. As I mentioned, there's like consistency issues. Folks might be familiar with something called a CAP theorem. Consistency, availability, and partitions, something. And you can never get 100% score on each of those. You have to pick a tradeoff. Vercel is talking about how, no, compute should be closest to the database. And you can use some of the newer technology, PPR, partial pre-rendering of pages. Those should happen closest to the users. And the fucking ecosystem loves three letter acronyms. Every two weeks there's a new one.

JASON: Yeah, that actually kind of pokes at something that I think is my biggest challenge with this space is that we seem to have approached it from the standpoint of like we have to own the thing. And I think that's what drives to make the hyperbolic claims is like when you talk about it, we pitch it as a panacea. We need to dominate this market, there's no room for anyone else here. We pretend as a company that we can do everything. And we hope by the time the enterprise use cases come in and prove us wrong, that we have enough market share and it doesn't matter.

SUNIL: Oh, yeah, 100%.

JASON: And this is -- honestly, this isn't the first time we have seen companies like Vercel do this huge sale, walk it back, huge sale, walk it back. I think it's indicative of it an issue with frontend tooling today. This has become a game that we play and it just burns people over and over again. But --

SUNIL: It's a -- but -- go on.

JASON: I want this to be -- I'm not trying to trash anybody. I'm noticing a trend I'm seeing concerning in the frontend space. So, what I want to talk about instead is like what are the more durable concepts? And the things that are going to continue to be true even once the hype cycle is down? And that's one of the things that I thought would be really interesting to talk to you about because it's pretty clear that serverless is, you know, it's been proven it's not a cure-all, but it is a very strong contender for a lot of modern app architectures. It's here to stay, I think. I don't think we're going to see serverless vanish as a fad. But it's a lot of challenges. That's where your head space has been lately with Partykit and beyond. I kind of want to talk about that. So, digging into serverless as a concept, we've learned that, you know, there's no such thing as serverless, it's just somebody else's servers. And I think the famous one, I can't remember who said it, was it Kelsey Hightower, serverless isn't a technology, it's a billing model.

SUNIL: That's right.

JASON: What a brilliant way to put that because it's very true. So, digging into this a little bit when we start to talk about what we're actually doing when we dive into this architecture. The way I've understood it, you are basically paying to borrow the unused space on somebody else's dedicated server, where you can spin up on request and then spin down to zero when you're not getting requests. The benefit of this is obviously you're not paying for unused server capacity or electricity you're not using. All the overhead that comes with running a server at all times. Now, the down side of this, in order to do that, spinning to zero means your app needs to be stateless. Anything that you need to be brought in has to be brought in at boot time so you're reading from a database, you're reading from wherever. You have got to read something off of disk. It can't sit in memory, there is no memory. And then make this post about stateful serverless. And, you know, my first thought was just to kind of narrow my eyes and look at you a little sideways because it didn't make sense to me. I want to talk more about this. And get a sense of what do you mean when you were talking about stateful serverless?

SUNIL: At the risk of being -- you should read my blog. You should read my blog. You should add a link to it later. But before I dive into it, like anything else, what I'm proposing is not a panacea. In fact, even if you look at like the Vercel messaging and I think the Twitter Medium also makes them sound a little bit more absolutist than they are. Like if you take -- if you take their position as an absolute one that they proposed yesterday, then what you should do is not really use -- ever use Vercel at all. You should be renting a giant -- well, a $5 VPS, and once you have users, you should get a massive machine, one for your database, one for your server. Attach it to a like a literal power supply, that should be a thing. But you shouldn't use Vercel at all. That's not what they're saying. They're open about it. It almost feels like they're swinging too hard back into the thing. So, stateful server -- so, using that as a launch-off point. So, like you said, the serverless model -- I think AWS invented the term. But the model is very much here. The moment a request comes in, it will literally spin up a little memory space or whatever. And you have to write a function which takes a request and returns a response. What happens inside that probably asynchronous function is up to you. You can talk to the database for it. And the goldfish function, the moment it returns that, it forgets everything and returns. And a little bit of nuance there, and you can keep a function, or, whatever. But framing it as a billing model is very interesting because now you have a billing choice affecting your software architecture. Before serverless was a thing, this was not how we wrote servers at all. You would write a Node app and you would use express router and you would literally run it and it would be running all the time. Some very simple benefits. I used to work for an ecommerce company. And the home page has banners. Like officer like these are the current offers, et cetera. And you -- you want to reduce database chatter in general because it can make your database follow it. Especially when it's something that won't be changing for the next couple of hours. So, what you do is you write some code is that says, hey, if when a request comes in for the home page, I'll have a little JavaScript variable. That's what I mean by state. That's just it. I'm not talking about another database. Like literally a const banners object. Okay? And you're like, hey! Are there banners for the home page in this object? If they're not there, go fetch it from the database, put it into this JavaScript object and return it. Okay. But if it's already there, pick it up from the JavaScript object and return it. And it's a similar cache -- cache -- I'm going to say cache. That is stateful programming.

JASON: Right.

SUNIL: You are actually depending on some state that persists across requests. This is amazing. And that's by the way, such a great way to deliver a performance win for your e-commerce website. It's instantaneous. All the requests are so fast. But there are tradeoffs as well. Because you have to invalidate this cache. You can't keep it there forever. When they change the banners on the database, you want the new ones to show up on the page. So, either you're demanding we restart your servers because the JavaScript state has to disappear, or you have to timer. You're like, if 5 minutes have passed since the last time you picked this up, then assume it's not there and talk to the database again. And now you have like a lever. You're like, okay. This means that any banner that we put in has a potential maximum of 5 minutes before it starts showing on the thing. So, if you reduce the amount of time, let's say you bring it down to 2 minutes, it will appear faster. But you get more charter on the database. And solving this problem in a good way, speaking to your business, makes you a senior engineer, I guess. Whatever. Cool. And this is the way people did things for a long time. This is what Node.js was really good at. PHP didn't do this. PHP even when you were doing it older, it would spin up a new request for every request and you would have to build a database for it. Having a model for this is great. Serverless came along and completely removed it. Can't do that anymore. Because like I said, goldfish memory, JavaScript variables, any state you hold disappears. By the way, feel free to use our per-API call metered read service -- AWS has 40 of them, every platform has 40 of them. Some service, oh, this is easy, it's not a full database, but you can use it almost like key value store. Which is fine. But what has happened then in the last -- what? 15? 20 years since this has been around is that programmers believe this is how you write servers. And that's a problem. When people say you should just use a Ruby server or a $5 VPS, it's not just that it's cheaper. It's that yeah, you can write code as simple as it used to be and noting to worry about stringing together 43-letter acronyms, okay? But it is a good model because like you said, it scales well. Like you can run it anywhere across the planet. It scales down so you don't pay for unused time. So, at in point I'm going to jump into -- I'm not really shilling Cloudflare, but saying Cloudflare has a solution. I suspect that other providers come up with some other version of this, okay? So, right now it's something Cloudflare does. I highly encourage other providers. Absolutely implement something like this. It's called durable objects. But it's not -- I don't like the name. It makes it sound way more exotic than it is. It's very simple. That's why I'm here to explain this extremely simple great idea. The idea is simple. Which is for a given ID, and we'll talk about what this ID can be, ABC, 123 -- instead of defining a function, you define a class, okay? You define a class that has let's say a fetch member on request. You define on a class. The first time -- Cloudflare's durable objects have two or three objects to it. Okay? So, the first time you make a request to this class, it will spin up an instance of the class. It will spin it up closest to the user that requests it. And it will run it through that member of onRequest. But then it stays alive. This is where the magic happens. And it's a class, remember. So, the second time a request comes for the same ID, it's alive. So, you could on the class and you could have an instance property -- is that -- instance variable. Like we said, like banners. That in your first request you actually go to the database fetch and like add it to it. But the second time you can return from that.

JASON: Okay.

SUNIL: There's no nothing. This is as simple as I can make it. It just keeps it alive. Now, does it keep it alive forever? No. If there's like no activity for -- actually, I don't know. A bunch of second. There's some nuance around it -- it shuts down. But then the next request comes and it comes back to life. Which is also quite nice.

JASON: And what it comes back to life, does it come back to life with the state or comes back and re-initializes?

SUNIL: It comes back and re-initializes. It's a middle ground. In the express days I would be able to basically guarantee that for as long as the server didn't restart I would have state in memory.

SUNIL: Correct.

JASON: In serverless, I have zero -- I have a guarantee that there will not be anything in memory when the function runs. And durable objects is a way of saying that like most of the time, assuming the serverless function is busy, it will have the -- the data in memory.

SUNIL: Correct.

JASON: Okay.

SUNIL: Little nuance here as well. In our previous model when we were writing express servers, this thing that you mentioned would be true only if you were running a single process on that machine. The moment you're using something like -- well, half the time I used to use Nodemon, I don't know what other -- since Node.js is single-threaded, you don't want it running only -- it would not use the 16 CPU, core CPU on your thing. You try to run 16 of them. Also, you wouldn't guarantee a request for a given ID goes to a certain process unless you write code for that. That's a different thing. It's definitely a little bit more powerful than that. Like you said, it's a middle ground in that the state might restart.

JASON: Right.

SUNIL: Conveniently, the code you write for the express server, you have to write defensively assuming it might restart at any point in time. Programming model is still the same. You know what? I should take this opportunity to say that there are a couple of players out there who are doing this thing where instead of shutting down the server, it actually hibernates the entire memory of the process and brings it back to life.

JASON: Interesting.

SUNIL: I'll tell you the two that I know of. I don't know if they're particularly big or popular. I just know they do it. One is called Gollum Cloud, the other is the WASM folks at Extism. Great, one of my ex-Cloudflare colleagues works there. Steve. He's great. By the way, that means that there are solutions also in play that are being built that go all the way. Oh, we have more requests. Let's literally do a serialization of the entire memory process. Is and when it comes back, you will actually have that. If I'm right, I don't think you can write JavaScript for those. I think those are like Rust and other friendly languages. Though I might be wrong.

JASON: Extism is like WASM. You can write JavaScript you have to compile it over using WASM to the Extism thing.

SUNIL: Yes. Amazing we have a spectrum of solutions. As you can imagine, there are tradeoffs with each of these things. But that we are now expanding that space in between full server to full serverless. And that's -- I think that space is the stateful serverless thing that I want to talk to you about.

JASON: Yes.

SUNIL: And what it enables as imaginary qualities. Have I explained to that point that it makes sense?

JASON: Yes, I'm with you.

SUNIL: Amazing. If you want to write code, we can write code, but we don't have to.

JASON: I think it would be fun to work through in the capacity of let's try to get to a working mental model of how we put that into practice. Why don't we take that opportunity to do that right now. So, I'm gonna share my screen. And we'll get the whole screen in there. There it is... let's get to a better view.

SUNIL: Hey, that's my buddy Steve.

JASON: Yeah, we had Steve on the show and talked about Extism. I dropped a link in the chat if you want to follow along. You can watch this episode, it was super-cool. We managed to get a Go app and a JavaScript app speaking to each other in the browser. It was really, really cool. Stuff that I didn't think I could actually do. And it's maybe the only opportunity to watch me write Go code. And then this was the article that you mentioned -- I dropped the link to this in the chat as well earlier. This is sort of what we're talking about today. And we are talking to -- you know what? I'm just gonna go to your home page because I don't know what the right thing to do is for sharing people's social media anymore. Because they're all -- all of them are bad.

SUNIL: That's fine, I have links to my socials on this. More blog posts.

JASON: Wherever you hang out, get in there.

SUNIL: I think the esbuild -- by the way, that's often I update my blog. The fourth entry is something we did three years ago.

JASON: I love. I love it. One thing I want to note is this episode like every episode -- and I'm going over here and check on the page. We have Nx and Netlify sponsoring this episode. Because it's being live captioned. We have Amanda here from White Coat Captioning taking down everything we're saying and making it more accessible. You can find that by going to the link that is scrolling across the bottom event page right now. I think we're picking up your hands again, Sunil.

SUNIL: Sorry.

JASON: On the keyboard. All good, all good. So, all right. Now that I've done that, if I want to actually build something using these objects, what -- what do I do first? What's my first step?

SUNIL: Let's open a terminal.

JASON: Okay. I'm going to open up code and use this terminal. Are we gonna -- we're gonna create a new project, I assume?

SUNIL: Correct. Npm create Partykit.

JASON: Npm create Partykit.

SUNIL: Latest, I don't know if you have -- okay. Cool. Yes. Okay.

JASON: We're gonna call this one "Stateful serverless."

SUNIL: Pick the types for starter. That's fine.

JASON: Okay. And we'll get into it. We'll open that one. And here we go. Okay. Let me actually get into this so we can actually see. There we go.

SUNIL: Cool. Let's open source/server.ts. Let's start from that, I guess.

JASON: Let me make this a little bigger. Source, server.

SUNIL: Awesome. We can actually make it -- let's start from something a little simpler. Just delete the on connect and on access message. Just delete it completely.

JASON: Get them out of there. Why are you --

SUNIL: Awesome. That's fine, that's fine.

JASON: Oh, that's just because we deleted all the properties.

SUNIL: Cool. We have literally just imported a type definition for the sorter and we put a constructer. The constructer is passed an instance of what we call a room, the thing that's associated within ID. And we talk about the IDs later but for the sake of the audience so it's not confusing, it can be product ID, a user ID, a game session ID. It's up to you to define what center your state around. That's all it is, okay? A room is a nice word. Oh, this is the room where we do all our stuff.

JASON: It's the room where it happens.

SUNIL: Right? Let's literally just do the example we mentioned. Add an instance variable called counter initialized to zero.

JASON: Okay. So, counter, zero.

SUNIL: Counter zero. All right. Let's add a method called onRequest. Nice. Inside it let's do counter plus, plus. And the counter --

JASON: Right, right.

SUNIL: And return new response with the value of the start counter. Why not?

JASON: What don't you like?

SUNIL: It needs to be a string. So, yeah, just wrap it in ticks or something like that.

JASON: Yeah. We'll do one of these.

SUNIL: Why is it still complaining?

JASON: That was because I can't write code.

SUNIL: Okay. By the way, this is the example. It's a counter for an ID. Every time you make a request to it, who knows what the request is? It returns -- it increments it and returns it. This by the way this model is so hard to do with something like AWS Lambda, right? Or even like a plain Cloudflare work.

JASON: I saw that post. I'm actually going to pull that up. Because I thought that was really interesting to see the contrast. And it also explains something that I -- because I had kind of -- in my head, I had this thought about like why didn't -- why don't I ever build stuff like this? Oh, my god, you post so much.

SUNIL: I do, I'm sorry. Yeah...

JASON: Where the hell is it?

SUNIL: Down there, keep going, keep going. That's the one.

JASON: So, this was the breakdown of how you set up a websocket.

SUNIL: So, if you want to do a websocket that just broadcasts messages to other connected people. Like you send a message and anyone who is connected gets the same message back to them. It's called a broadcast, by the way. It's the simplest, most common use case for websockets. Like oh, you're -- it's the basis of everything. It's absolutely mental how you do this in Lambda.

JASON: Yeah, it's not just Lambda. It's Lambda with API Gateway which goes into DynamoDB and then we have to send a query for every single message for a list of current clients --

SUNIL: Clients --

JASON: Right. Which is --

SUNIL: I saw the sample project. It's not fun.

JASON: And like, you know, the structure of this isn't the sort of thing that -- it doesn't sound that wild when you think about why -- like how they got here. And I think that what makes it challenging is that it's -- it becomes very clear very quickly that this is not what Lambda was intended for, right? And I think that's -- that's sort of the, you know, it's not -- it's not that Lambda inherently confusing, Lambda is super straightforward when you use it what it was built for. But so many of the things that we -- that we work on just don't -- like we twist them to try to be something that they're not. It's sort of the nature of the web, and I think where something like Partykit even comes in is like we were all doing this a very hard, bad way, which created space for somebody to come in and actually solve the problem as a first class use of the tool. So, okay. So, we've got that.

SUNIL: All right, so, we will work ourselves up -- we will work ourselves up to that use case, okay? But this is just a simple one, okay? The counter. So, you have saved it. Run npm run Dev in your terminal, I guess, just to make sure. Make sure it's running locally.

JASON: Okay. So, local host 1999. STUDENT: Open up -- that's the thing with the way we do URLs. Open up the slash party, slash ABC. Okay. /party, /ABC. It takes ABC as the party. That's around that. You are seeing the number 1. Now start refreshing the stage. Keep refreshing. Every time you refresh it, it updates. Open up this URL in a new tab.

JASON: Let me see... oops. Nope. It's the -- what am I trying to do right now?

SUNIL: It's trying to print. You'll see the same number. It's not the same thing. Every time you refresh, it's the equivalent of doing that --

JASON: Why can't remember --

SUNIL: Demand D.

JASON: Add split view. Jesus Christ, that's what I was trying to do.

SUNIL: In both. You actually saw is, I think like --

JASON: Oh, interesting, you see that?

SUNIL: Come back.

JASON: Yeah, it's like --

SUNIL: Refreshes, synchronizes to the same number. We haven't done that with websockets yet, but it's the same thing. Yet. And it's sharing state. Every time you make a request, it gets the latest count. Amazing. So, in this choose your own adventure journey that we are having, would you like to make it solve it so that it persists even when the server shuts down and off? Or do you want to just go to the websocket stuff.

JASON: Let's -- yeah, let's do the websocket stuff because I think that will make it more interesting when we get into the shutting down and starting again.

SUNIL: Awesome, awesome. Okay. Cool. This is what we're going to do. We're going to add an onConnect method.

JASON: Okay.

SUNIL: What you're going to do -- onConnect connects every time it goes to this instance. The interesting thing -- the magic, but really the simplicity of it, every websocket for this given ID is going to connect to this same process. The state that's alive. That's why it is awesome. So, what you can do here is onConnect, say -- this might -- you might not need an onConnect as well. Delete the onConnect. We don't need an onConnect handler.

JASON: Who cares? Get it out of here.

SUNIL: Who cares? Make an onMessage handler. Let's get it for every message that comes in, it's triggered. So, onMessage, if message equals -- literally if message equals increment, the string increment, let's say.

JASON: Okay.

SUNIL: This.counter ++. Inside --

JASON: Oh, inside.

SUNIL: Inside the thing itself you can say this.room.broadcast -- this counter.

JASON: Why are you mad?

SUNIL: Make a string.

JASON: Type number is -- oh, got it, got it. Got it. Whoa. What am I doing right now? Stop hitting every one of those buttons immediately.

SUNIL: Exactly. Cool. The code is as simple as it is. Every time the client sends a message saying "Increment" you're going to update the counter and broadcast it to everyone. Nice. Now open up client.dsx. I think there's a client file. You can see that we have import party socket. That's basically it's a thin layer on top of like -- on top of websocket, which by the way, you can use a plain websocket as well. Why I like party socket, it reconnects any time a connection drops. It buffers messages. Just a bunch of nice things. But it's a drop-in replacement for websocket stuff.

JASON: For anybody who hasn't written their own websocket, it's just worth it. The amount of effort you'll spend when you find that like we're getting intermittent disconnections. Or why did this websocket stop receiving messages. It's goofy stuff, if you know to check for it, you have to check, just use Partysocket it will make your life easier.

SUNIL: I think that's one of the big successes of Partykit, just having the websocket to choose from.

JASON: Yes.

SUNIL: Let's delete some code and make this simple. And let's remove everything below 24. I think you should be able to do it. Yeah. That entire set. And let's remove whatever is inside that addEventListener. That's going to -- cool. To explain the code here, Partysocket, we have a connection to an app element, which is just literally a div on the HTML page. Nothing fancy. It's just literally got element. Thanks, MRVDOG. MRVDOG gets it. You can see I opened up a connection that's a new party socket to that host and my new room. Just works. Now, inside the addEventListener, every is equal to HTML.event.data. Okay?

JASON: Easy enough.

SUNIL: We should also put in -- okay. Added line underneath 8 which says, hey, const button is going to document get element by ID element. This is breaks every access rule, by the way. But we'll do it for right now. Nice. And install element, button.addEventListener.onClick. That's right. Connections --

JASON: And say connection.send?

SUNIL: Beautiful, yes.

JASON: And increment, right?

SUNIL: Amazing.

JASON: Look at this go.

SUNIL: Look at this go. Fantastic. We could also do thing for initial state, but let's keep it simple. You want to open up index.html, by the way. So, we can add that little button element. Yeah. Right underneath the div. Underneath the div. Outside the div.

JASON: We don't have an output. So, we need our output.

SUNIL: Yeah. That is the app element. You can delete that code.

JASON: Oh, app. I was thinking it was called -- okay. Gotcha, gotcha, gotcha. Then we are going to set up a button and the button is going to have an ID of what did we call it?

SUNIL: Increment.

JASON: Increment. And we'll call it type button, why not? Had and then we'll say increment.

SUNIL: Yeah.

JASON: Okay. So, then --

SUNIL: I want to say we're done maybe?

JASON: Let's find out.

SUNIL: And open it up thanks, Darshak, you get it. It's enough abstraction without feeling like magic.

JASON: Welcome to Partykit.

SUNIL: Okay.

JASON: Welcome to Partykit.

SUNIL: Okay. What?

JASON: Look at that.

SUNIL: What?

JASON: Okay. Now I can break it, though. If I refresh, it takes one click to get us back in sync.

SUNIL: It does. Because we don't load an initial state when we do that.

JASON: Right. So, to do that we would just onConnect send this dot thing, right?

SUNIL: Should. Why not just send --

JASON: I mean, like it's so straightforward that it feels like it's silly not to. On connect -- not that one. OnConnect. And we would say --

SUNIL: Just broadcast the thing. Just broadcast to the entire room. Connect, maybe. Yeah, do it only for that connection. Because --

JASON: Connection.send. And then we just send this.counter.

SUNIL: Love it.

JASON: Right? And -- oh.

SUNIL: No, I think that should work.

JASON: It won't send... yeah.

SUNIL: Let's see. Let's try it out.

JASON: Okay. Here we go. We're gonna try. Look at us go.

SUNIL: Look at us go.

JASON: And we can make that a little bit less ugly by getting rid of this bit here. So, that's not -- we don't get that flash. Otherwise...

JASON: Beautiful.

SUNIL: Love it!

JASON: Look at us go.

SUNIL: By the way, I want to point out something right now. We have already solved that AWS Lambda Tweet thing we saw. It's done. The whole you spending a few hours and setting up four services and figuring out how it will cost you. No. You wrote some code that just works. You can broadcast all messages to all connectors. People are saying such wonderful stuff in the chat. I'm reading it all.

JASON: Isn't it a great chat? I mean, I'm not -- I'm a little biased, but I think I have the best chat on the planet.

SUNIL: And by the way, I'm so happy to be taking credit for all of Cloudflare's work here.

JASON: Adds is tradition.

SUNIL: As is tradition. But let's just go back to the code for a second. Let's go to the server. I want to like -- there are hooks. Those are life cycle hooks. Whenever a fresh connection is made. There's onStart asynchronous function. If you need to preload your state with something from a database, you can do something there. And it's asynchronous, which is super-nice. It means -- and it like holds -- like it keeps websocket connections. It puts it in the holding pattern until const start is finished. There's onRequest. It's fairly -- like it's straightforward. Like I don't think I introduced any new computer science concepts here. By the way, the whole broadcast thing -- somebody might be like, well, broadcast does a lot of complicated stuff in the background. But I added broadcast because it turned out to be to common everyone doing it, the implementation for broadcast is affordable. The room is holding all the websocket connections in an array, and any time you call broadcast it just does a fore loop and sends the message. It's one line of code that does that. This is what stateful serverless can do. So, this server will now stay alive while there are any live connections to the thing. That's the nice thing about websockets, by the way. That's the live websocket connected to this. The room will actually stay alive. And it scales nicely as well. Do you want to put this in the chat and let everyone click increment?

JASON: Yes. For me to do that, I run --

SUNIL: Run deploy.

JASON: Why?

SUNIL: Maybe it will work. Oh, you already logged in with Partykit at some point.

JASON: I am logged in with Partykit, yes.

SUNIL: This is a first time deploy of the specific project. It will take two minutes. My job description doesn't involve making DNS fast. I'll work on that later. We can chat, I guess. Try opening that.

JASON: Okay. Just wait a minute for the SSL to provision.

SUNIL: This is -- look, for the last year and a half I have been talking about multi-flare and CRDDs and building game servers and collaborative text editing and AI agents. And while it's all very impressive, what -- something that took me a few months to realize is that not everyone knows what's going on in my head. And I was like, oh, I need to like explain the fundamentals for this first before I try explaining everything else. But whatever you have seen right now, this is the code foundation for everything on top of it. Everything else is just npm install library and do stuff. You want to build a workflow engine that updates in the background, you can reset. You want to build a collaborative shared text editor like Google Docs? Yeah, use Yjs libraries and wire it up to the editor. But at core, it's the space that can spin up and stay live while you do whatever it is you want to do. And it spins down when you're not using it. It doesn't make serverless -- there are tradeoffs. And we can talk about the tradeoffs as well.

JASON: Yeah.

SUNIL: But to go back to where we came from, this is not a panacea. Don't rewrite all your serverless functions for this. Serverless functions are great for so many other things, right? Stuff that just has to read from a cache somewhere, a quick request, an API endpoint. Those are great. And there's a set of tradeoffs there. You should look at stateful serverless as a new tool. As something that lets you do things without having to lean on one of these extremes. Your $5 or $500 VPS or AWS Lambda. Cloudflare workers. All of these things that let you do these magical things.

JASON: Yeah, as we're talking about these, maybe one thing I'm thinking of, so, we're sort of deploying like a counter. Which is the Canonical example of how you show somebody how this stuff works. And we're gonna add the durable objects to it. But when we start thinking about these in practical terms, like what are the use cases that you think this -- this really shines for?

SUNIL: My -- let me start with a couple of my favorites. The one thing that a lot of -- over the last year and a half a lot of kids show up inspect Partykit Discord. And they're like, hey, we built a game and it works really well. A multi-player game. Suddenly strikes me this. Websockets landed in Chrome in 2009. The spec was in a 2008. So, it's 15 years since websockets have been in the browser. So, teenagers will try to build like a game over the weekend. And it will work locally on their laptop or machine or whatever. And then they look at what it will take to deploy it on to the Internet. And then they get into -- because serverless doesn't solve the problem. They need to provision machines. They need to provision machines across the world, use something like Redis or something to do websocket synchronization to make sure all ends up in the same process, et cetera. What started off as a weekend project -- oh, and they need to hire a bunch of senior engineers to maintain these clusters. Shipping this weekend project suddenly becomes a multi-million dollar investment. Okay. I'm not going to do that. Don't get me wrong. Like part of it is a hard distributed systems problem. It's not a mistake that it's taken trillion dollar, multi-billion dollar companies to build Google Docs, Figma, game studios. Anything. Partykit inverts the physics of it. This is not a user learned solution, this is a new infrastructure primitive that's so freaking cheap. I'm glad Cloudflare acquired Partykit because trying to build revenue on cheap service is a bit of a challenge. It's cheap and it makes it accessible for even on the planet to build stuff like this. So, I start -- the one that I'm really almost proud of and my favorite is people building game servers. Hey, you want to build a quick game. It can be as simple as a game like tic-tac-toe. Or a 3D fighting game set in like something else. Like there are people who are running like full game engines inside of these Partykit rooms.

JASON: Yeah.

SUNIL: Where people are collaborating and fighting. Okay. So, that's one. The second one that a lot of people are probably familiar with are how do you build Google Docs? Shared text area? And in that same space, how do you do collaborative drawing spaces? Is it working?

JASON: It is working.

SUNIL: Let's -- yeah. Just try it out. Make sure it's still working.

JASON: All right, chat.

SUNIL: By the way, look how fast it synchronizes across -- it's not peer-to-peer.

JASON: Right, this is browser to edge node to browser.

SUNIL: Okay. Everyone is clicking the button. There it goes.

JASON: Has somebody set a loop up already?

SUNIL: Probably. I wouldn't be surprised. Look at it go.

JASON: And then as I refresh, we can see that it just keeps on ticking.

SUNIL: Yep.

JASON: Right? So, this is -- to me this is -- the fact that we kind of built that as an after thought as we were chatting through these use cases, I can't really imagine -- I worked on -- on real-time apps back in about 2015. It was one of my very first React projects was trying to put together -- what we wanted was presenter software so that the leader of a group could run a workshop and people would be able to watch and see like the leaders video and a slide show and we needed all that to sync. I was into the WebRTC stuff, websocket, it was like a nightmare. Everything was buggy, everything was flaky. Even the idea of building this reliably was like a multi-day, stressful thought. And we just sort of did it. Like we just -- oh, whatever. It's fine.

SUNIL: It's like production-ready, scales across the planet. Yada, yada. But it's nice, it works. So, building something like Google Docs is three or four hard problems in one. The first one is the infrastructure. Which we have claimed to have solved with Partykit. The second one is how do you make sure that whether you're both editing the same block of text -- this is making me nervous, by the way. Can we move away from seeing this number incrementing.

JASON: Yes.

SUNIL: The screen.

JASON: We'll just go back to this one. My safety.

SUNIL: Okay. This one. Cool. So, the second problem is how do you make sure you're seeing the same thing? Two people are editing the same word at the same time.

JASON: Okay.

SUNIL: It's not enough to do what we just did, broadcast changes. It's the timing of the state on the frontend versus the backend. It's a synchronizing problem. There's a wonderful, wonderful open source library called Yjs that solve this is problem. It uses a data structure called a CRDD. And I'm going to attempt to you what the full form of that is? I think it's a conflict-replicated data type. Something. CRDD -- whatever. The point is it takes all these changes and it puts it on funky math algorithm on top of it. And it makes sure that you're seeing the same thing in a bunch of places. There are -- this is built by a guy named Kevin who spent the last few years of his life on this. Building this wonderful open source library. It's so good. So, one is that it implements a hard thing, and the second is the ecosystem around it is amazing. There are a lot of web-based editors, Code mirror, conflict-free replicated data dives. I was close. It's fine.

JASON: You were in the ballpark. That's fine.

SUNIL: Thanks. There's a crazy ecosystem around that. Which is amazing. Like the community is amazing. Lexical editor, draft editor, slate editor. If there's a web-based editor, there's a Yjs backend for it somewhere, okay? Writing a Yjs backend in Partykit is about four lines of code. We don't have to do that right now. It might take this thing. But I'm so proud of that. So, I took Yjs and built like a Partykit wrapper around it. And I put it out there. And suddenly people show up in the Discord. In fact, one of my favorite things to do, I would be having a call with a probably user or a customer. And be like, do you want to do this on the call? Do you want to build and deploy this to production on the call? Really? It's one of my favorite feelings. Yeah, let's just copy/paste this, deploy this, point your thing to it, we are good to go. So, what used to be something that would take a Google to solve is what everybody now has access to. The reason I bring up text editors is because it's adjacent to another hard problem which is collaborative drawing. And that's where Partykit of the born. Partykit started because after I left Cloudflare I was looking for interesting problems. I was hanging out with the team at tldraw. It's a wonderful, free -- free as in -- online drawing space. In fact the demo now we can do, let's go there for a second and mess with it if you want.

JASON: Yeah, let's do it.

SUNIL: Open it, hit the share button on the top right.

JASON: Wait. Let me open a new thingy.

SUNIL: Hit the share button. Don't copy the URL into the chat, okay?

JASON: Okay.

SUNIL: You never want an open text area or camera space. I know your group is awesome. But there is always that one person. And so, copy that link and share it with me. Remove that QR code like really quickly from the screen.

JASON: Okay. How do I? There we go.

SUNIL: Twitter DMs or something.

JASON: Throw it in the chat here.

SUNIL: Okay, sweet. So, pick up a pen and start drawing, I guess.

JASON: Let's see if I can do the Steve Ruiz

SUNIL: Not even close.

JASON: He's way too good at it, it's so annoying.

SUNIL: The bits I'm drawing, let me change the color. Aren't being batched or anything. They're coming in as smoothly as I'm drawing them.

JASON: Right.

SUNIL: Okay. Previous to durable objects and the new tech that's popped up, this is now a multi-month, multi-million dollar senior engineer almost a Ph.D.-level projects.

JASON: Right.

SUNIL: Inside of Partykit we built a prototype in a week and we were in production in six weeks. This is where Partykit was born. I closed the window. But and to go deeper into it, it was with three people. And none of whom are operations experts, DevOps experts or anything. They have a genius with David Sheldrick who wrote the custom engine that does all the CRDD-ish stuff. But seeing that you could build a world class experience like this for a small -- I mean, I call them a small team, but they're a team with taste and excellent engineering abilities. It means that anyone can do it. In the, take tldraw to Partykit and deploy it. It's amazing.

JASON: Right.

SUNIL: Another favorite use case of mine. I don't know how much more you want me to go into this --

JASON: Let's do the -- I want to make sure we get the durable object implemented before we run out of time. So, I want to pull us back so we can persist our count between reboots.

SUNIL: Amazing. Let's do that right now.

JASON: All right. So, I'm gonna pull us back into the code. And I'll just start us up, npm run Dev again, and I'm ready.

SUNIL: Let's go back to the server. So, the problem we have is that the state is now like in the memory which will disappear when the server shuts down. You have an option of now using a database if you want to. But what's fun about these objects is that they come with the -- like each instance, like per ID, each of them comes with a little key value store. Like its own storage for like -- you don't have to use like a database for like a bunch of use cases for which you -- for this use case. So, anywhere you have like this stored counter, instead read it from room.storage now. So, let's open up the onConnect now.

JASON: Okay.

SUNIL: And instead of saying this dot counter, say await.this.room.storage.get counter. Like literally inside that --

JASON: Let me pull this out. So, current count is await. This dot --

SUNIL: Room.

JASON: Room.

SUNIL: Dot storage.

JASON: Storage.

SUNIL: .get. Counter. Maybe when it starts off it won't have any value at all. Maybe you want to say R zero.

JASON: Okay.

SUNIL: Connection and current count. Which is also make a decision, I guess.

JASON: Oh, okay. All right. Got to be a string. Okay. Okay.

SUNIL: One second. I want to make sure -- wait, get counter. Yep, I think that -- yep. Now let's --

JASON: Do you mean the right promise void? Isn't that what I did?

SUNIL: Oh, remove the void or -- it's now an async function. Remove the first part of it.

JASON: Got it, okay.

SUNIL: Let's move to the onMessage thing. You can remove the onRequest.

JASON: Oh, right. We're not using that anymore, are we?

SUNIL: Then you can say await this.room.storage.put counter value.

JASON: Okay. So, we're gonna say... const. When I do --

SUNIL: Just do an update

JASON: Okay. so this.room.storage.put. Counter. And this counter ++?

SUNIL: We don't have a distort counter anymore. What would be a good way to do this. You need to get the current value. Okay. Sorry. You actually do need to get the current value before doing it.

JASON: Okay. So, we'll say current count plus 1.

SUNIL: That's right.

JASON: What are you mad about?

SUNIL: Because it thinks it's --

JASON: Oh, hush you. Now what are you mad about?

SUNIL: So, okay. So, in the .get you can get -- this is just TypeScript. Why don't you just say "As number" for now?

JASON: Yeah. Leave me alone. Be nice to me.

SUNIL: Delete this, plus, plus. Since we're not doing that. And broadcast current count ++. That's fine.

JASON: Does that -- wait. Hold on. Does this -- does this like store?

SUNIL: It will, it will. Yeah. So, you want it to send current count, yep.

JASON: Okay.

SUNIL: And again, it has to be --

JASON: Oh, my god.

SUNIL: TypeScript, man.

JASON: Just be nicer to me, TypeScript.

SUNIL: This should -- maybe this should do it.

JASON: That should be it?

SUNIL: I think so. Try it locally.

JASON: Okay. So, we should have local going... but then it breaks. So, we're not getting -- something is not right.

SUNIL: Can you do console.log of what current count is?

JASON: Yep. Console.log. Current count. Current count. Also comes back as one.

SUNIL: Oh, did we do -- oh. I know what the problem is. That should be ++ current count, not current count ++.

JASON: Oh! Because we want to do it on the -- before we write. Okay.

SUNIL: Refresh the page. There we go.

JASON: There we go. And now if I stop this and start it again, we should still have the values?

SUNIL: Actually maybe? Try it.

JASON: Let's try it. Okay. So, I've stopped. I'm starting.

SUNIL: Yeah.

JASON: Oh, neat!

SUNIL: It's because it's storing it locally on disk. And whether you deploy it on Cloudflare, it will store it in the room. Why the + is in front? Linda, it's because JavaScript is a pain. If you pass it current count ++, it would give you the value of current count to the function that called it and do ++ afterwards. Instead, if you do ++ current count, it does the addition, the increment before presenting it to where it's being used. I actually don't like this behavior about JavaScript.

JASON: That is one definitely of the behaviors I see why you did that, but... come on.

SUNIL: Yeah.

JASON: But yeah. So, okay. This -- so, is this using Wrangler?

SUNIL: No. But it is using the core of Wrangler, which is Cloudflare runtime mini worker called Miniflare. Wrangler has -- I wrote a big portion that have wrangler as well. But, of course, the team has done so much more after that. I will still take credit nor it. That's just how I am. But I did build like my own layer. And the reason for that is that Partykit adds a bunch of boilerplate and it talks to the API and makes using durable objects like a lot simpler. Usual objects would be like extremely low level. And durable object migrations and the way they do bindings. I was like, wait, I can get a computer to do that. And literally build a company on top of it. So, no. You can call this like -- it's not Wrangler, it's close to. In spirit, it's close to it. And now part of the journey I have in Cloudflare is how to bring those lessons into Wrangler and the rest of the stack. But you see what's going on here which is --

JASON: Yes.

SUNIL: Oh, if you are persisting it to disk -- and by the way, that disk is happening literal flit same space that this instance is, that's why it's so fast. And it's per-room. If you open it up for another ID, like it doesn't share the storage.

JASON: Got it.

SUNIL: But it means that the moment that this room wakes up, it can pick it up from disk and you can persist any like local state like to. And it's a very simple get. There are some other -- like you can list all the keys that you've used.

JASON: And so, is this the durable object?

SUNIL: This makes it durable, yeah. This is the part that makes it durable.

JASON: Got it. So, when would this -- when would this value clear? Like do I -- is the only way that it will clear is if I manually clear it?

SUNIL: That's right. Or you delete the entire durable object binding which is a way to do it as well.

JASON: Okay.

SUNIL: Which is to say, yeah, if you delete the project, it will disappear.

JASON: Got it. So, basically what this gives me is for my individual rooms inside of my Partykit server, each one gets a key value store that's unique to the room.

SUNIL: That's right.

JASON: What I mean by "Room" is here we're setting this. But if I was using a JavaScript router -- like earlier you had me go to /room/ABC. I could set up something similar, my app, slash, session, slash, whatever that ID is. And that ID gets used as the room. So, each ID gets its own durable objects.

SUNIL: 100%.

JASON: Got it.

SUNIL: Now you can see how this works with -- when you click the share button, it generated a random ID and that's the ID under which all the code runs. Who you make a game session, you invite the person in the particular ID. You build -- for example you want to synchronize state between writing an app and you want to synchronize it to all your devices because we live in a multi-device world. Then in that you use your user ID. Any ID with that ID, it's a synchronized state. A workflow system, every return of a workflow would be one of these IDs and underneath that you would have one of these desserts. Just a very simple, powerful primitive against which you can do other stuff.

JASON: Yeah. A use case that just got brought up, would a common use case be lazily writing to the database as well to get the state back after the durable object has died?

SUNIL: 100%. To be clear like the durable object is not just the storage, it's also the code. That's why I say the name isn't like great. But yes, you can use this to write do a database as well. What you can do is use in-memory for a bunch of fast stuff. Or even like the room.storage. But either every 20 seconds, you can push stuff to a database. Whenever everyone disconnects, flush it to the database before it disappears. You can write the code, yes.S answer is yes and the answer to how is you get to beside because you write the code that does it all.

JASON: This is really cool. I love the core concept that is basically when I'm in this session, I can use this key value store to have extremely fast reads and writes to memory in a way that will still be present even through a restart of the room.

SUNIL: Is that right.

JASON: If I need to then move that somewhere else, like I can see, you know, if I -- if I'm running like a SaaS app, I would have my user accounts which might be coming from Okta or Clerk or something like that. So, there's data there that has to be synced up. I might have, you know, project data in postgres or MySQL. I might have other data in different places. But the active session stuff needs to be faster than like a database read halfway around the world. So, I can let the user do things that are live-synced instantly through these durable objects and then as you said, when they disconnect, we have a hook for that. OnDisconnect, is it onClose? OnDisconnect?

SUNIL: Which is the websocket, you will say onClose.

JASON: Right. We can run this onClose here. When somebody closes their connection, take all the current state and write it back to the database so when it opens again, we just pull that state back in and you basically have like -- yeah, this is a really, really powerful model for things that need to be very fast. And like you said, like it doesn't feel -- I don't know. I was expecting there to be more to it.

SUNIL: No.

JASON: Like I'm very pleasantly surprised that this just kind of worked.

SUNIL: Actually, I'm still surprised. But I think I'm surprised because of the trauma of like doing serverless programming. Despite having literally built this myself. Every time it works, wow. That was eight lines of code. This is going to be a really short Learn with Jason session.

JASON: This is perfect. This is exactly the sort of thing that I've wanted to exist because I let -- what I like about the serverless model is it's a very -- it's like a clean slate or the of approach. Where things that used to kill me in Node and stuff like that were like slow memory leaks. And I don't know if it's my code or one of the dependencies I pulled in or whatever. But I noticed that it starts out and I'm using 20 mega bytes and check back a week later, using a hundred. I don't know why. I have to reboot the server. Then looking at cron jobs to reboot the server. At that point, you're stateless anyways to reboot your server to avoid the memory leak. That's silly. But stateless, you don't get memory leaks in stateless, as long as you don't let a process run away with your serverless execution. So, you just run it and like you said, it's a goldfish. It just -- it runs, it forgets, it runs, it forgets. But the issue of database stuff, when I want to pull something in, I have definitely written serverless functions that read from a postgres database and they take like two and a half seconds to run. Is that the end of the world? Absolutely not. I've used banking apps. It's still fast by that standard. But it would be cool if it wasn't that slow. And the fact that we're doing, you know, when we look at this, the fact that this is actually a like key value store read-write happening. And it's this fast with the server round trip. Because remember, this is not peer-to-peer. This is I click in this browser, it goes to the edge node. It writes the data, it reads the data and then it sends the data back here and then this one updates. That's ridiculously fast.

SUNIL: I just want to answer the chat message here. So, you could get the initial info from a DB, do all the live stuff local and then just take the local state at the end and send that back to the update. It is that straightforward. You don't have to come up with a complicated architecture. All is happening in the class that's going on. One of the tricks that like doing is inside that onClose function, I check to see what the length -- you can get a list of all active connections by calling room.get connections, by the way. Say this.room.get connections. It's an iterator. What you want to do is spread is inside an array, by the way.

JASON: Right. So, we would get like const, connections equals... whoa.

SUNIL: Dot, dot, dot -- okay. And then dot length of that gives you how many active connections there are. What that means is I will flush to my database only when this is zero. Like whenever the last connection levels. Then do something to a database. Ah, such a lovely, simple model. I love it.

JASON: I mean, this is really, really interesting stuff. Another way you could do it too it we know who the sender is, right? Because we have the current connection. So, we can also like if, for example, we had -- we were hooked into user accounts through some auth provider, we could use the connection to store any session data to our user. Like our user was last seen at... and throw is that in, right? So, little things like that we can do that -- like historically felt so hard to do. And yet here we are two, three lines of code and we're just like yeet! There we go. It's done.

SUNIL: Yeeting it. I will -- there are a couple of -- I don't want to go into like features. But one of the simpler things -- let's say that you want to -- how would you even do this with like serverless? I don't know. Okay. I want to save all the data to my database every 30 seconds. So, how would you do it with this model, I guess? Like what is your first thing that comes to your mind?

JASON: I mean, my initial thought is that we would want to set up some kind of -- I mean, can I just like -- can I just do this?

SUNIL: That's exactly what I'm saying. And just the rule that you call every 30 seconds that saves to database. Yeah.

JASON: Right?

SUNIL: Probably better to put it inside the constructer. You don't want the rule to start on every websocket connection.

JASON: Oh, that's true. We want it down here.

SUNIL: I'm saying this is ridiculous that we're even talking about it. Yeah, just put it in an interval and run it. Clear the interval whatever the connection -- Whatever. You can write all the code that does whatever. This is why I keep talking about like foundational like primitive like low-level stuff. You can have a conversation on Twitter about, oh. Edges but serverless, serverful is good, Node.js is good. And it loses so much nuance when a primitively comes along, it says I assume you want to ship a feature to production today. Let's just get to it.

JASON: Yes. Okay. You just articulated something that is so important. There are tools that have entered my world that I feel like fundamentally shifted wait I think about delivering code. For example, when I first started using a component-based framework, it fundamentally shifted the way I thought about writing code for the web. When I first learned about get push to deploy, it fundamentally shifted the way that I thought about building for the Internet. When I learned about decoupling frontends, it fundamentally shifted the way I thought about building for Internet. And this is another one of those moments where I'm actually -- I'm thinking about using real-time in a way that before it was always like, yeah. You know, maybe someday if I have like income and it's like, you know, we can afford some employees we would look at this. But like now it's like, that could be a day zero feature because it takes so little time to set up.

SUNIL: Yep.

JASON: Like, this to me -- and in combination with the fact that now we've got things like, you know, the database as a service that does feel just as good as, you know, writing to a JavaScript object, really, if you look at how some of these things work. It's pretty incredible how much we can do as frontend Devs without jumping too far out of the JavaScript mindset. We just get to build stuff now, we just get to ship stuff now. The limit is less and less can the tech handle this and more and more can we imagine what it would look like?

SUNIL: That's exactly it. I don't know if you noticed this -- I bet you do because you're also a person who does this -- I don't involve myself in the discourse on like social media. First of all, the medium is not very good to have discourse-discourse. But also, everyone uses it to like score points. And tell you how smart they are -- how -- look at how good I am at this advanced technology. And I'm --

JASON: Right.

SUNIL: Yeah. The most complicated thing that I can think of as an API for this is like a class. Let's just do that. No one is talked -- and like ship and like -- I have like movies to watch and like guitars to play. I have no time for the rest of your -- this thing. So, it's interesting times.

JASON: Yeah. And I think -- I mean, this -- this really does strike at the heart of something that I have been feeling for a long time which is this sense that I feel like as an industry we've sort of lost sight of why the code is cool. We spend too much time trying to like prove why a certain tech is superior, but we're trying to prove it on like esoteric, academic merits as opposed to looking a the what we're shipping and who the whole point of this, you know, is that we are trying to deliver something valuable to the people that we're -- whoever our audience is. And I don't -- like I feel like if I were -- if I had contractors coming into my house and instead of building me a new kitchen they were arguing over whether or not they should use like a certain type of wood or a different type of wood, it wouldn't take very long before I would want different contractors. Because you're not doing the thing I hired them to do. They're wasting time on details that -- they matter, but they don't matter tough, right? And like obviously, if one of them is arguing for like building it out of dry pasta and one is arguing to build it out of wood, that's a very different thing. But at a certain point, you know, like --

SUNIL: Yeah, let's just take a call.

JASON: It doesn't matter. Just go and build me the thing and it's gonna work. And like the differences are so academic once you get past a certain point that it's -- it's not important anymore. And I think that this, again, going back to the very beginning of this call, one of the things that I think we've done is we've -- because the fact that we've got so much venture capital in software now, in DevTools in particular, we can't talk about things in -- in like practical terms anymore. Because that doesn't drive revenue. So, we have to talk about them in hyperbolic terms because we need people this think one solution is bad and the other solution is good. Really it's a hammer and a screwdriver. They solve different purposes, they're for different things. But ultimately if you're not using them to build something useful, you're just collecting crap and not getting anything done.

SUNIL: There's -- in the musician world, there's something called GAS -- gear acquisition syndrome. Which is you buy all the best guitar pedals, you buy like a room for all your guitars, four different amplifiers. You take pictures of them and you share your opinions about how warm the tone is and what the exact knobs have to be, et cetera. None of these people actually play their instruments. This is because of what -- I'm one of those people, by the way. Like disposable income goes on little gadgets that I can feel really good gathering dust on the shelves. We almost do that with npm libraries.

JASON: Yeah.

SUNIL: And then like we go on Twitter and talk about them. Look at the shiny npm library that I have. By the way, it's the best. If you don't like it, you're a bad person, Jason. You're so bad.

JASON: This like cuts me to my core. I really don't like that so much of the industry has become about identity. Like are you the right kind of developer? Are you associated with the right group of developers? It's like, you know, we build for the web. Like at end of the day, we're rearranging dots on the screen. We're not cool enough to have cliques and in-groups. We're glorified dot re-arrangers. It's fine. We get paid so well to rearrange these dots.

SUNIL: Oh, my gosh, we get paid so much.

JASON: Like taking it this seriously hurts my heart. We do a fundamentally silly thing for money. If we treat it like it's somehow fun, it's the best thing in the world. If you treat it like it's somehow tied to you as a human being, it's not pun.

SUNIL: You will never be happy if you become that person. Cool. That's -- yeah.

JASON: Well, your connection or my connection is starting to give up. I think that might

SUNIL: Did I freeze?

JASON: One of us froze. I'm going guess it's you. The chat is still rolling over here. At the end of the day, we're LEGO connectors. I love that. What's up, Mettle X. Welcome to the stream. With this, I'm going to play us out because this was super-fun. I feel like I learned a lot and now I have a new tool in my belt that I'm excited about. Where should people go if they want to go keeper?

SUNIL: Partykit.io, we have docs and starter templates. You can literally run npm create Partykit in your terminal right now and make a project. We have a Discord. I love my Discord. It's, again, linked to on this page. Also by the way, this Partykit, the page itself is a multi-player thing you can see in the diagram if you move your mouse across it. I just love it.

JASON: Yes, you can see the play happening here. And I like that it shows where people are coming in from too. This is fun.

SUNIL: Yeah, little flags as well. That's one of the fun things. It didn't ask for location permissions. So, once you have like a network that's so well-spread across the world, each of these requests just tells you which data center it's coming from and it's scaring -- well, it's obviously accurate. Yeah, we know which country -- it actually has information down to almost the neighborhood you're in. But I figured that would freak people out if I started putting this on here. But yeah. Just because like you can add like flags.

JASON: Just show everybody a picture of their front door.

SUNIL: Yeah, that's it. Just look. It's a little app --

JASON: That is absolutely terrifying.

SUNIL: I am personally on Twitter, as you know very well. I have a screen addiction problem. You can find me there or on the Discord. Build something new. Show up, share it with everyone. Make it open source so that everyone can build. And yeah. I'm excited to see what you've -- look, I'm working at like a level -- at like a DevToolsy level because I think I'm too old to come up with great like ideas now. And I now lean on the rest of you all to like take this stuff and build amazing things on top of it.

JASON: I mean, we all need the foundation so that we don't have to learn how all of this stuff works. You know? I think I'm grateful that I never had to learn how punch cards or bytecode work. And even more grateful that I didn't have to learn how to make websockets reliable. I'm very grate to feel builders like that.

SUNIL: By the way, I have to tell you, once you start hacking on stuff with Partykit and websockets, it's addictive. Like it's so much fun. You can build like so many cool things. Just go for it.

JASON: Very much agreed. All right. Let me do a quick shoutout to our sponsors. We've had Amanda here with us from White Coat Captioning taking down the words available at the link you can see scrolling across the bottom the screen. And Nx Netlify making this show more access to believe more people. I very much appreciate it. More stuff coming up on the show. Brandon Roberts on May 9th. I have other shows that I need to get up on the site immediately. Because clearly the schedule is not complete. But they're coming. We'll get it done. You can get on the Learn with Jason Discord if you want. If you want to keep up on what we're doing here. Make sure that you like and subscribe and do all the things on YouTube on Twitch and whatever to make sure that, you know, if you're enjoying yourself, let other people know. It helps me out, it helps you out, it helps the community out. We're all gonna have a little bit more fun together. With that, thank you all so much for hanging out. We will see you next time.

SUNIL: Thanks, folks, bye!