Loading
Interviews with Experts Bonus 25 exercises
interview

API Mocking with Artem Zakharchenko

Artem, the mind behind MSW (Mock Service Worker), discusses with Kent his experience with the development and broadening scope of this essential tool for developers. Originally conceived as a weekend project in the Czech Republic, MSW has grown into a resource for API mocking, debugging, and specialized production applications.

When it comes to adaptability, MSW doesn't disappoint. It integrates seamlessly with both browser and Node.js environments. Unlike traditional mocking methods, which replace native modules, MSW enhances them. This allows for more nuanced control over HTTP requests

With additional capabilities like GraphQL support and Storybook integration, MSW proves itself as a versatile tool for a variety of developers.

Looking ahead, plans are in place to simplify WebSocket implementations and make the tool even more user-friendly. Both Artem and Kent agree that community involvement and financial contributions are vital for the continued growth and improvement of MSW.

Resources

Loading interview

Transcript

00:00:00 Kent: Hey, Artem, how's it going?

00:00:02 Artem: Hey, Kent. It's great. What about you?

00:00:05 Kent: I'm doing great. And everybody watching right now, hopefully you've been enjoying the exercises and stuff. Artem is the creator of MSW, which We're using in the workshops, and it's awesome been working on that for years now. I'm gonna try and pronounce your last name you gave me a a guide Let's

00:00:25 try that Zakharchenko

00:00:29 Artem: is really close. Yeah, yeah,

00:00:31 Kent: okay, okay? Can you say it?

00:00:33 Artem: Zakharchenko, I think it's pretty pretty much

00:00:35 Kent: the same. Yeah. Well, okay. So your pronunciation guide was very helpful then. Because I look at your, the spelling of your last name and I'm like, I have no idea how to say that. So yeah, thank you. Well, so Artem, why don't you introduce yourself to folks listening?

00:00:52 Artem: Yeah, sure. Hey there. My name is Artem. I'm a software engineer based in Czech Republic. I've been fascinated by computers and engineering in particular since I was about 12 years old. And I've been doing this as a hobby for a very long time before it became my full-time job. And like many years

00:01:13 later, here we are.

00:01:15 Kent: Awesome. Well, so can you dive a little deeper into the creation of MSW and what with like the stuff that you've been working on, what really led you to create MSW, this tool that we're, that I really love?

00:01:34 Artem: I created MSW as a kind of over-weekend pet project. I wasn't really satisfied with the state of API mocking libraries back then. I think it's about, it's like 5 years this year, 5 years ago. And I decided, yeah, like time flies. And I thought to myself that we can do better. And I kind of

00:01:54 created this prototype very hastily as prototypes usually are. And you know, turned out we can do better. And over time I had a chance to iterate on it and improve it. And now you folks are all using and hopefully enjoying it in your workshop.

00:02:10 Kent: Awesome, yeah. I can tell you how I came to start using MSW. I think you actually know, but I'll tell other folks who are listening. So I was working on Epic React and the material for that and getting into doing like

00:02:31 working with a Pokemon app or component that we were putting together. And I wanted to teach how to do fetch requests and things. And so the challenge that I was facing is I didn't want to require people to set up a real server and run that server for the workshop. I wanted

00:02:51 to keep it really simple. And so I built a little fetch mock. I say window.fetch equals my own thing. And it mocked things out and it worked fine. But it wasn't the most ergonomic thing for me to develop with. It didn't like, users at the workshop had no idea that this was going on,

00:03:11 so it was fine. But it just wasn't very nice to work with. And then on top of that, I missed the ability to see the network tab and see the actual requests going through, right? So that's when I started exploring using a service worker, but I'd done service workers before and I

00:03:31 was like, yeah, that sounds awful. I don't want to write all this stuff in a service worker. There's so many edge cases with service workers. And so then I started looking around, and somebody recommended Mirage.js, which is a popular library for mocking. But Mirage does pretty much the same thing that what I was doing, just mocking, making their own version of Fetcher.

00:03:52 I don't know exactly their implementation, but the bottom line was no network tab. And so like, that wasn't any better from what I was doing. And then I discovered MSW. And the thing that really surprised me about MSW was that I could actually write my fetch handlers within my Create React app, like within that source code.

00:04:12 And so I didn't have to write anything in the service worker and MSW would handle the service worker for me. And that was like sold. I was super, super into that. And then on top of that, soon thereafter, you added the ability to use the same handlers in the browser as well as in

00:04:32 Node, so I could use it for testing. And that just like, oh, chef's kiss like this, just it was so, so nice. So yeah, since then, years ago, ever since then I have loved it. I wrote a blog post about you should not mock Fetch, stop mocking Fetch because MSW

00:04:53 is the answer. So thank you.

00:04:56 Artem: Oh, thank you.

00:04:58 Kent: Yeah, it's been awesome. So yeah, can you tell us a little bit about some of the, so actually let me back up really quick. So with the, in Epic Web, none of the workshops are using MSW in the browser. And in fact, In my active development, I don't use MSW in the browser because

00:05:19 I'm doing full stack development and so all of the requests that I'm making to third parties that I want to mock out are happening on the server. There could be some integrations that are client-side only in the future, like for certain features, there's, you know, you wanna use, oh, I

00:05:39 forget what it's called, but there's this API for doing autocomplete on an input for addresses and stuff. Google has 1, but there's this other 1 that I used at a company a while back, and yeah, proxying that through your server was not ever gonna work. So like doing stuff like that, those types of integrations, I totally would 100% use MSW in

00:05:59 the browser, But for most of the time, I end up only using it on the server. And so I really would like to get an idea of how MSW works at that level. Because in like MSW, for those who don't know, it's mock service worker. You know what that means. But we're not using the service worker at all.

00:06:19 And so there's obviously, like there's no service worker on the server side. So yeah, I think it'd be kind of cool to hear about how did the server side aspect of MSW come to be? And how does that work? How do you make that happen?

00:06:36 Artem: That's a really cool question, because I remember people asking about this when the project just started, and folks started writing posts about using MSW in Node and praising its service worker capabilities, but that was kind of mutually exclusive. There's no workers in Node like service workers. And the way it works in Node is very similar to

00:06:57 things like Knock, if people use that. And it's similar, but a bit different. So to give you a bit of a history context, most of the tools in Node do like patching of request making modules, very similar to how you mentioned you override your fetch, like window.fetch, but library

00:07:17 authors actually do like http.clientrequest or http.get, and they just take and override those classes and functions to make them do whatever they want, which is also not without the trade-offs. Like, how I see this is when you override these native modules, you are throwing a big portion of their

00:07:37 logic away, and you are trimming them down just so they do whatever the mock requires. And I, like you may guess, I'm not a big proponent of that because well, I believe mocking should be as transparent and as production kind of resembling production as possible.

00:07:55 Kent: Yeah, so

00:07:56 Artem: what we did with, yeah, like what we did with MSW was take a slightly different approach. I believe right now what you're using is like version 4 of this approach, but the idea, it didn't change. So the point was to take these native classes, let's take a HTTP client request as an example. This is 1 of the most used APIs

00:08:16 in Node. And before like global fetch, like a year or 2 ago, this was the main way to make requests. And what MSW does, it creates an extension of this class. So we don't override it, we extend it. And this allows us to go into things like, for example, this is the method when request happens. I don't want to override it.

00:08:36 I want to kind of listen to it. And if there is a mock for this particular request, I want to hijack it. But if there is no mock, what I do is basically super.end, for example. And this is so powerful because it means I'm not throwing away everything that Node does. I'm just strategically kind of listening to

00:08:56 proper events during the request. And what I've been experimenting recently is even better than that. There was a proof of concept to use proxies, where proxy in JavaScript is basically an API that wraps any object and allows you to react to changes that

00:09:17 happen into that object. So you can listen to new properties being set or functions being called or classes being constructed because if you think about it, everything in JavaScript is an object. And I already rewrote the XMLHttpRequestInterception using this approach and it's fantastic. I literally had a kind of a revelation

00:09:38 the other day. I was debugging something, and I opened this class that provides mocking for XMLHttpRequests, And it took me a couple of minutes to realize where the mocks are, because it just doesn't do anything drastic. It takes the proxy, and it listens to particular events, like load start and load end, and that was it.

00:09:58 Kent: Wow, that sounds interesting. So the work on MSW and fine-tuning the way that it works, the implementation is never done.

00:10:07 Artem: It's never done, no.

00:10:09 Kent: Yeah, so since you're extending the class, you need to override what happens when a module says import HTTP. How do you manage that?

00:10:19 Artem: So what we have is a concept of Interceptor. It's a base class that basically does 2 things. It patches some modules. It can be actually anything. You can use it for whatever module you like, but we use it for this HTTP module in particular. And it does some patches to make your modules, and

00:10:39 then it has a dispose method that reverts all those patches. And in fact, it reverts all the side effects that you might have introduced, the side effects you need to make this particular interception work. Because it comes down to the fact that you can make requests in Node in many ways, actually. Like, there is HTTP client request, which is the main way, but people are also using

00:11:00 things like GS DOM without realizing this is actually Node, right? It's just a smart abstraction that makes you think you're working with a browser. So you have things like XML HTTP requests and even fetch historically. But all those were implemented under the hood using the same Node modules. So in Node.js, we also have first-class

00:11:21 support for those, so it's a little easier for us to manage. And, yeah, so this is what we do, effectively. We create Interceptor, And then we can also group them together because it will be really annoying if you would have to configure things if you're suddenly using not HTTP client request but something else in Node.

00:11:41 So we do this for you, and we have another concept, which is a batch interceptor. And effectively, all it does, it groups multiple interceptor instances together. So what most people are using when they import MSW slash node is actually a batch interceptor that combines client request, XHR, and fetch as

00:12:01 well for modern versions of Node. And this is how they get this API mocking working.

00:12:08 Kent: Yeah, wow, that's honestly really fascinating how all that works. So, Can you tell us a little bit about what you see people using MSW for and like where can people integrate this into their workflow?

00:12:27 Artem: When I first created MSW, obviously the main goal was to help people mock APIs in a better way. But over the years, I've been honestly blown away by what people are using MSW for. Like, apart from obviously testing in Node.js, people are using MSW to prototype

00:12:47 their apps because 1 of the applications of it is that you can have a state when you have to develop a front end, but your backend isn't ready, or it has an issue, or you're developing on a train. You know, anything can happen. And what I love people doing is they just grab MSW and they describe the same request handlers they probably have in tests because you use it. It's

00:13:07 just 1 network description. And they just enable it whenever they want. And suddenly they're developing against a particular state of their backend APIs, which is fixed in time. It's never going to change. It's there. And I absolutely love it. And I think it's also very powerful for debugging. Like when you encounter something

00:13:28 breaking in your app and you're certain it has to do with the data you're fetching, so something isn't right. So with MSW, you can actually emulate any data coming from any APIs, even those you don't own, and you can pinpoint the issue, and then you just copy the same handler into your test, and you have this one-to-one reproduction

00:13:48 that is always reliable and allows you to write a regression test for that. And yeah, I think there are also a couple of unusual use cases, like I know you're using MSW in production sometimes to kind of emulate the server that is running for some of the apps that you maybe built. Yeah,

00:14:05 Kent: I used that for Epic React, yeah.

00:14:07 Artem: Yeah, yeah. That's really cool. People also employed a lot in tools like Storybook because effectively those tools are centered around showcasing different state of your app. In this case, it's about UI state, but very often your UI state depends on something else, like network. So

00:14:27 people are using our add-on for Storybook, and they can say, hey, this is how this component looks when there's a server error. And this is actually pretty easy to do. And I think this is a match made in heaven.

00:14:39 Kent: Yeah, yeah, absolutely. I remember before MSW, Storybook was always a big pain because you had to figure out, well, how do I mock out the data that comes into this. And so I guess I'll, this is, I think, part of what motivated the idea behind the smart and dumb components or container and presentation components, right? So that your presentation components would be the ones that go into Storybook and

00:14:59 then you just don't put Storybook on it. But if you have the network mocked out, then you can totally do just your container components in Storybook. And you can do the whole app in Storybook if you want to. Which is nice. And like it all comes back down to, Storybook is just another type of a test. It's

00:15:19 a manual test, like you actually have to pull it up and run it. Of course, they have their testing stuff too, which is also very cool. But even with the manual testing capabilities of Storybook, you want to make your code run as close to the production code as possible so that you're actually testing more stuff.

00:15:40 And that's just 1 of the things that I love about MSW is that I don't have to change my source code at all to be able to make this mock stuff work. So my tests can live over here and my source code can just pretend that, or behave the same way in production or in test mode, which I think is just so key. I think

00:16:00 That's 1 reason why you and I just are so aligned on the tools that we've made. You with MSW and me with Testing Libraries, we both have this really strong feeling that your tests should resemble the way your software is used. And by doing that, you just

00:16:20 get a lot more confidence. So yeah, I think that's awesome. Now, I know that you have done a little bit of work, or maybe a lot of work at this point in other kinds of protocols, more than just HTTP. And so I'm talking specifically, oh, well, actually

00:16:40 before we get into like, I wanna talk about WebSockets and SMTP and stuff like that too. But before we talk about that, MSW also has support for GraphQL, which as somebody who has used GraphQL only a couple of times, I thought was kind of interesting. And I don't know with the new

00:17:01 version that you're working on now, is GraphQL still a first-class citizen, or is it just part of the HTTP mocking abilities now?

00:17:09 Artem: It is first-class citizen, as it's always been. And the same way as you could do it before, you can, of course, describe APIs, GraphQL APIs using HTTP handlers, because thankfully on the web, GraphQL is most often done using HTTP. But we do ship a designated GraphQL object, so you can mock queries

00:17:29 and mutations much easier.

00:17:32 Kent: Yeah. Yeah, I suppose the reason for that is because it doesn't make a whole lot of sense to say, okay, HTTP post, here's my GraphQL endpoint, and now this is my handler, and it's like literally anything you can do is all going to be in here. So that makes a lot of sense to have a utility, especially for like if you're

00:17:52 selecting these things, then here's what should come back. Yeah. Okay, great. So I'd like to talk about WebSockets and SMTP. Which would you like to mention first?

00:18:06 Artem: Oh boy, let's go with WebSockets.

00:18:08 Kent: Okay, great, yeah. So, WebSockets for those who are unfamiliar, that's all about doing two-way communication between the client and the server. So server can send messages to the client and vice versa. Did I say that right? Server can go to client, client can go back to the server. It is not HTTP,

00:18:30 And so that brings with it a different set of challenges. Yeah, I'd love to hear about those.

00:18:36 Artem: Yeah. So WebSockets are really, really great for, as you said, like full duplex communications, and they're really cool for like real world, like live kind of applications, like chat and collaborations, but they do come with a set of challenges. So yeah, first of all, it's a different protocol. And

00:18:56 historically in Node, there hasn't been a way of working with WebSockets at all. I don't believe they ship API that allows you to kind of construct WebSocket connections natively right now. There is an effort behind that, but it's not that simple. And what people ended up doing is basically building custom libraries like Circuit.io,

00:19:16 which rely on quite a number of things, but in a nutshell, they just rely on native Node primitives to implement WebSocket protocol as you may be used to it on the web. And The main challenge to me, like somebody who may want to bring WebSocket support to MSW, the main challenge

00:19:37 is that there isn't a single way how these kind of connections are done. So, to give a bit of history, Websockets do have their own protocol, but Websocket connection can also be implemented by regular HTTP polling. What that does is basically you ask the server every n seconds

00:19:57 whether something has changed, and then if it did, you receive an event from the server, so it relies on a long polling connection to the server. And this, as a client, this gives you kind of the reality of being in a live communication with server. And this is great, but you can already see how, okay, WebSockets can actually be done

00:20:17 over HTTP2, but that's actually not everything. In Node, as I mentioned, there isn't WebSocket protocol, but instead, other third-party libraries, they rely on the concept of transports. So they can use and like opt in and out of different transports without even you knowing that includes HTTP

00:20:37 polling, that include, I believe, row socket connections, and they also have XHR polling for certain situations, I think mainly meant for the browser. And this creates quite a cascade of complexity because to you as MSW user, I want you to just type a WS or WebSocket dot, I don't know, on particular event and then respond

00:20:57 with a particular event back. And this was historically very difficult to achieve. I do have a prototype which dates like a year or 2 ago back and it has WebSocket support for the browser, but the node part is difficult. I've been asking for, like asking around about this and also

00:21:17 open for any contributions there, because we need to figure out how do you achieve this on the common level possible, because I would hate to implement each transport separately. I would love to have this common denominator upon which then all this transport from third party libraries build upon. And this denominator is effectively

00:21:39 net dot socket in node, which is a raw socket connection. And I spent some time looking into this and I achieved some pretty cool results with observing these connections. This is actually pretty, like this is a good scenario when you can use proxies that I mentioned, but emulating responses from the socket

00:21:59 connection becomes really difficult. You're basically so low on the network layer in Node that not only you're dealing with raw HTTP messages, which is strings, but you're also dealing with things like buffer parsing and encoding, and you need to replace way too many things for it to work, so I would like this approach.

00:22:19 So it still remains in discussion. Maybe by the time I get back to it, a committee behind Node.js will actually ship an official Node.js, like a WebSocket API. That would be really good. But until then, it's just exploration and discovery.

00:22:37 Kent: Yeah, yeah, wow. So these sorts of things are always more complicated than you think. Oh yeah. So yeah, That is very interesting. Sometimes when I hear about stuff like that, I sit back and think, how I can't believe this stuff works at all. It's amazing that

00:22:57 it works. So yeah, awesome. Thank you for sharing that background. Is it a similar situation for SMTP for like sending emails and that sort of thing?

00:23:07 Artem: It is similar, because I believe it's also done through socket connection. And it was 1 of the sessions that I had when you asked me about the ability to mock SMTP. And I looked into sockets and, well, you have intercepted those, but as I said, it becomes quite problematic to mock those reliably. And I don't think I

00:23:27 liked the end result that I achieved, so I put it on a break.

00:23:32 Kent: Yeah, that makes sense. And for those going through the workshops, this is actually the reason, the primary reason that we're using Resend's API for sending email instead of the SMTP and NodeMailer and all of that. There is definitely a benefit to using SMTP because

00:23:52 it means that you can swap with any other email provider that uses SMTP without changing any of your code, allegedly. But I have swapped email providers before, even using their REST APIs, and it's not that big of a deal anyway. So, and then on top

00:24:12 of that, we can mock it. And so I'm actually fine with that. So, yeah, very interesting. Is there anything else that, oh, you know what? Let's talk about the process or process communication stuff. So in the workshop, in the testing section, we have this onboarding

00:24:33 flow. And we actually have a couple of things, like we have verification emails and different things that are sent. And to test those, we of course don't want to send a real email and have the browser go to the email client and open it up, all that, that would be ridiculous. And so we do have the mock, but to communicate between the mock and the playwright browser is really difficult

00:24:53 because the, our dev server that has the mock in it is sitting over here in process A and it could maybe even a different terminal that you're running it in. And then your Playwright tests are running in a completely different process as well. So communicating between these processes is non-trivial. And so what we do in the workshop is we,

00:25:14 the mock will save the email to disk and then the Playwright Browser will just wait until that file has been written and then read it like it's reading an email. That works well, and I have no problems with this. But that's not good enough for Artem. And so, I would like to, and there

00:25:34 actually is a issue with this approach, and that is what if you wanted to mock out what happens if the email fails to send or maybe there's like some API failure, and So you want to change the mock for resend for this particular test. And that with the approach that I have right

00:25:54 now would be very, very challenging. You'd have to, what I would do right now is I'd have a special email address that when you try to send to this email address, that will trigger a failure in the handler, which I have done before. We did this at PayPal and companies have been up before and I hate it so much because there's

00:26:14 a strong layer of indirection there. And so, this is actually why I'm really excited for what Artem is working on. So can you tell us about this process-to-process communication?

00:26:24 Artem: Yeah, yeah. So my main motivation to even look into this was the rise of React server components, because to my limited understanding, they kind of consist of 2 parts, of the server part and the client part, and those are often done in 2 different processes for various reasons.

00:26:45 But the core idea is the same. You have 2 unrelated processes, but they are related by functionality, by React server components in this case. And I was thinking, well, how will folks test this? Because if you want to test it well, it has to resemble this architecture to some extent in the test. So you have to have kind of a...

00:27:02 Kent: You may be the only person asking the question, how will people test server components? So thank you for blazing the trail there.

00:27:11 Artem: Somebody has to. Yeah, and I was thinking how could this work in kind of in perfect world. And I do believe that we will arrive eventually to this task emulating this architecture. So we would have a mock server kind of part, which is responsible for service side logic, and then

00:27:31 you will have a client part, which is how we used to test React components right now, conventionally. But again, if you kind of copy this architecture into your test, you will also end up with 2 different processes. So how do we solve that? Because what you want to achieve is full control of a network. But in this case, the network lives in a different place

00:27:51 than your task lives. And this poses a problem. Now you need to have these 2 processes communicating to know about each other, to affect each other. And I looked into a more conventional IPC, which is inter-process communication, that Node provides. And it was interesting, but I ended up on the idea of basically doing something similar

00:28:11 to what you're doing with writing files to the disk, but instead of file system being the common place for this processes to communicate, I lifted it to a WebSocket server. So this was encapsulated in a brand new API, which isn't out yet. And the way it works is that you have a function that is called

00:28:32 setupRemoteServer, and it works very similarly to setupServer that you use for regular Node.js mocking, but with a twist. You basically delegate the interception of requests to a different process, and we use WebSockets to communicate this intention. So how it works is, let's say you're testing a play, you have

00:28:52 a playwright test that runs a remix app and you want to change the behavior of your loader function, right, which is on the server. And the way it works is it runs the interception in your app and it notifies your test through WebSocket that hey request occurred and your test is the area responsible to

00:29:12 describe how to handle this. The same way how we use service worker just for the interception, right? You don't write mocks there, it would be too cumbersome. The same way here, we use this WebSocket and your server just as the source of requests. And they signal kind of the requests that are happening to your test. And in your test, you have all the same request handlers,

00:29:32 all the same ability to do .use and reset handlers and all that. And once you provide the intention, it is sent back to your running server and also using the WebSockets. And then when you send a certain intention, like a mock response, it is used on the server and that's basically it.

00:29:52 Kent: Okay, yeah. So I just think this is brilliant. I think it's a really clever idea. I really like how similar this is to the idea of how the WebSocket or the service worker works. It just really makes a lot of sense. I think that's actually a pretty cool aspect of the design. So 1 question

00:30:12 that I have about implementation of this is right now what I have is I start my my dev server, whether I'm testing it or not, I have MSW running so that I'm not actually sending emails as I'm, you know, developing and everything. And so If I want to be able to

00:30:32 swap out the implementation of handlers and things, my assumption is that I will set up the mock service worker or the, yeah, I'll set up the mock server just like I do in, during development, but I will also say set up remote servers

00:30:53 or server. Is that right? Or do I do both or is it just 1?

00:30:59 Artem: I'm trying to recall right now how it's done, but I do believe you need both. Let me remember. Yeah, I remember how it's done. So basically, it's done in a way that you would need this setup remote server API, but on your kind of controlling side, which in my

00:31:19 example before was the test. But on the server side, you don't need any of that. On the server side, you just use regular setup server API. And the way MSW works, it kind of knows about a certain agreement between these 2 APIs, and if it's met, if it can kind of detect an open handle from your test asking

00:31:39 for, hey, I'm here, I'm ready to accept remote requests, it will just connect and send the traffic there. So that's how it's done.

00:31:47 Kent: I see, okay. That makes sense. So then in my test, if I say, okay, I want to, you know, server.use for this particular API, I want it to fail, right? That's my new handler. So the dev server actually has a handler for that, but because we added an override for that handler,

00:32:08 it's when the dev server makes this request, it's gonna say, oh, there's an override on the remote server so let me send it over there instead.

00:32:14 Artem: Yeah, that's good.

00:32:16 Kent: Awesome.

00:32:17 Artem: Yeah, it's pretty easy. Like we literally have the list of handlers, which are usually just your handlers in this process. And with this API, we're adding a preceding kind of check, which is like get me remote handlers, whatever, for this request. And it checks the remote connection first. If it handles the request, it uses that handler, that response, for example. And if

00:32:37 it doesn't handle anything, it just goes through your already existing handlers.

00:32:41 Kent: Very cool. And when that WebSocket server goes down, then the dev server no longer needs to check, right? So like if I stop my playwright tests, then that remote server is no longer listening for any responses. So the dev server just continues with its regular stuff.

00:32:59 Artem: Yeah, it will be terminated, yeah. Yeah,

00:33:00 Kent: yeah, that makes tons of sense. That is so cool. Brilliant. Definitely looking forward to having that capability. And so I wanna wrap up our conversation talking a little bit about how your work is supported and like how you make this sustainable because you do have

00:33:21 a full-time job and like you've got to be able to support yourself while you're doing this. Like does your employer or like how do you pay for this? How do you live? How do you make this sustainable?

00:33:38 Artem: Well, for a long time, it wasn't sustainable at all. In fact, when I first started kind of seeing the attention that MSW was getting, it was a bit overwhelming, and I ended up doing something very wrong, which was devoting almost all my free time to this project. Well,

00:33:58 of course, it resulted in the project moving forward and getting new features and kind of, you know, having more reasons for you to love it. But like the backside of it was me kind of not feeling very happy about my life. Like, I don't think it was healthy to spend like every evening and almost all weekends on this because I have family

00:34:18 to support, they also need me. And overall, I learned, like with time, I came to realize that the balance between these things is really important. And 1 of the things I learned from you actually is just addressing things that I'm personally interested in, which sometimes means that people are raising

00:34:39 issues and I just don't see this as something that I'm excited about. So I urge for contributing. I'm trying to keep up like up to date documentation and how anybody can join and help. So this is open source, the whole point of it. And yeah, like, by other means, of course, I was very lucky to

00:35:00 get into GitHub Sponsors program so people can support MSW officially, financially through GitHub and Open Collective. I believe you were actually the first GitHub sponsor I got. Oh, wow. Amazing. Happy sponsor.

00:35:14 Kent: I'm thankful.

00:35:14 Artem: And right Now we have around 13 sponsors for MSW, which is insane, and I'm really thankful for every

00:35:20 Kent: person in the company. It's not enough.

00:35:23 Artem: Yeah, I mean, it's not enough. People may not realize it, but even something as small as MSW can spawn really quickly. Small in terms of like the promises we make, like we don't make like thousand promises. It's just a small tool that does 1 job and it tries to do it well. But even that takes a

00:35:43 lot of time to maintain and test. And honestly, I'm very happy with kind of amount of time I'm able to dedicate to it. So I don't want to rush things. I would prefer being slow instead of being fast and breaking like thousands of people's like CI and tests. Nobody would appreciate

00:36:03 that. But over time, it became difficult to sustain this financially. I've been trying different ways to reach out to companies for sponsorships, to participate in some grants. They were not very successful, unfortunately. So if you are watching this by you aiming a viewer and you like MSW and you think it's a cool idea

00:36:23 and it deserves more love, then please consider supporting. You can support obviously through GitHub sponsors and Open Collective, but you can also support through contributing, which I find the best kind of support. We are still a very small team. It's insane to me that there's so many companies that rely on MSW, like Google, Microsoft,

00:36:44 Amazon. Really, there are countless companies, and still nobody really supports the effort behind it. It's still like this joke about huge enterprises being laying on the shoulders of 1 guy in some USA state. It's pretty much the same story. I maintain it as the only active

00:37:04 maintainer, but I'm very happy to have a few team members who help me with their judgment and who can reach out and pull requests and even tackle some things in a timely manner. But it's still not enough. And my main regret is that I can't really do this full time because you've been seeing what MSW already did to

00:37:24 the whole landscape of API mocking, which is really great, but it's a very small percentage of what we actually can do. But there is only as many hours in a day and I still need to pay for rent and I still need to, you know, have food. So obviously this is being sort of deprioritized.

00:37:43 Kent: Yep. Yep. Well, I am happy to sponsor and I recommend anybody who is making money off of code that's running through MSW should, just send a penny every time your code goes through MSW. Or just sponsor a little bit.

00:38:03 I think that's a good thing to do. So thank you for all the work that you've done. Is there anything else that we didn't cover that you would like to make sure we cover before we wrap up?

00:38:15 Artem: I think we're good. I think we covered through everything and I'm really happy to be a part of this course. Your support has been incredible. I'm very thankful for it. And I hope that people also enjoy what they will be building and learn a lot from MSW and from other things as well.

00:38:30 Kent: Well, thank you so much, Artem. All right, thanks everybody. We'll see you later.

00:38:34 Artem: Thank you, see ya.