
The Weekly Dev's Brew
Join host Jan-Niklas Wortmann in 'The Weekly Dev's Brew, where we explore the latest in web development, JavaScript, TypeScript, and emerging technologies. Engage in coffee shop-style conversations with industry experts to learn about frameworks like React, Vue, Angular, and everything remotely related. Follow us on social media for more insights https://www.weeklybrew.dev/
The Weekly Dev's Brew
From Discord Helper to OSS Maintainer (w/ Dominik Dorfmeister)
What does it take to accidentally become the maintainer of one of React's most popular libraries? In this episode, we sit down with Dominik Dorfmeister (aka. TkDodo), maintainer of React Query (now TanStack Query), to unpack his unexpected journey from answering Discord questions during COVID to maintaining a library with 10 million weekly downloads.
Dominik reveals how spending months just helping people on Discord led to becoming a core maintainer of the TanStack ecosystem. We dive deep into React Query's stability-first approach, the challenges of managing breaking changes across multiple frameworks, and why the React adapter is surprisingly the most complex to maintain.
From deleting 20,000 lines of dead code at Sentry to building platform teams that enable developer productivity, Dominik shares insights into maintaining software at scale.
Our Fantastic Guest
Dominik Dorfmeister
Software Engineer from 🇦🇹, working at Sentry, maintaining TanStack Query
BlueSky
Links and Resources
Dominik's Blog
Query.gg
Knip Docs
Thank you very much for listening!
We are also pretty much on all social media platforms, so make sure to like and subscribe!
Homepage - https://www.weeklybrew.dev/
BlueSky - https://bsky.app/profile/weeklybrew.dev
Instagram - https://www.instagram.com/weeklydevsbrew/
TikTok - https://www.tiktok.com/@weeklybrew.dev
YouTube - https://www.youtube.com/@theweeklydevsbrew
LinkedIn - https://linkedin.com/company/the-weekly-dev-s-brew
So Dominik, you got into the open source space, at least very publicly known, by starting to work on ReactQuery. How did that come together? How did that happen? That is, I think, one of the questions I get asked the most, which is why I've recently also written a blog post about it. It is a very interesting question. I think the story on how to get into open source is probably unique for everybody. But for me, it happened during COVID when I didn't really have like that much else to do, I mean, we couldn't go anywhere. And I thought I want to give back to the community a little bit. So I joined the Tanstack Discord server because at that time at the company where I worked, we were already using three products of the Tanstack. We're using Tanstack Table and the virtual library. And I didn't know much about the implementation. I didn't know anything about how this was written actually. So I thought I'd just join the Discord and look around and see who has a question and maybe can help answer the questions because I was a normal user of those libraries and that's pretty much what I did for the first, I don't know, probably four to six months. I did nothing but answer questions to people on Discord. You know, some of the questions were relatively easy for me to answer because I had those problems myself and I knew what I tried and what worked and what didn't work. But as time goes on, two things happened. Like, first of all, a couple of questions I had to repeat themselves. And I was like, I don't want to answer that question again. So I started to write a blog because, you know, that's what you do when you get a question like two or three times, you just write it down so you have something to link somebody to. That's kind of how my blog started. And that also got got quite popular then. But the other thing was that I there were some problems that I hadn't faced before because, you know, I didn't use all part of the library. Maybe it was a question about server side rendering that that we didn't do at the time. Or maybe it was just a question about some parts that I hadn't touched yet. And I thought that's an interesting question, interesting problem. How would I fix this? Right. Because I think most of the time when the community is relatively new or not that large and you ask a question, sometimes you get no answer at all because somebody says, I don't know, I'm not going to look into it. But I was I was really curious at the time and I had a bit of time. So I actually made reproductions for people that filed issues that they didn't make reproductions. Looking looking back, that's kind of like, I don't know, I wouldn't do that now. Yeah. But yeah, so I looked into all that, all the different things, even though I didn't necessarily have the problem myself. And then I came up with either with solutions. And sometimes I found out, yeah, you know, that that's a real bug in the library. And now let's try to try to fix that. So I got to through answering questions, I got to know the library pretty well. And then I also looked at the source code and kind of like things started to to make sense for me. And that's yeah, that's how I slowly got into this position of knowing a bit about the library. And then at one point, you know, Tanner reached out and said, hey, you know, you've made a couple of PRs, you want to merge them yourself? Like here's the here's the invites to the repository. And that was something I had never even like considered or thought that would happen. So I never had the plans to to become an open source maintainer or anything. I was just there to, you know, help people with their problems. And that was I think this is a for me was the perfect start into open source because it was also very rewarding. Right. You don't need to know the code, understand everything, because it's hard to get into existing projects. We all we all know that from work. It takes some onboarding time. But when you when you answer some questions, you know, I always had this instant gratification because people were super happy. Hey, there's someone who actually reads my problem and wants to help me. That's that's that's so nice. Right. So there was always this positive feedback I got. And then most of the time, it just took me a couple of minutes to read through the question, answer it. And everybody was super happy. And, you know, that there is someone who engages. And and I got better at knowing those things myself. So I think it was a win win. And I think it's very important to understand that open source contributions are not just about writing code. It's also about the community. It's about helping people. And yeah, that's how I started on. One thing that I think is always very interesting when I talk to people is like how their career shifted once they joined into open source or became more active in the open source space. So I'm curious to see how that was for you. Did you notice like in a bump in like LinkedIn outreach or something like that? Did you notice like a positive impact on your career other than the improved knowledge in that particular area? Oh, yeah, it was it was wild, actually. So I got like tons of tons of people reaching out to me when I was at Twitter. I had a pretty active and pretty large Twitter audience as well. So I got lots of VMs about, you know, jobs or also things about what people wanted my help on specific topics. Because of that, I started to do consulting on the side. I've always been self-employed. So that kind of like was always an option for me. So I'm still doing that, by the way. So if someone wants to, you know, need some help with the React projects, TypeScript, React query, I'm always happy to help. And then, of course, UI.dev reached out to me about making a course about React query once that became popular. So that was a kind of a different career path I hadn't considered becoming like someone who makes a course and earns a little bit off of that. I got invited to conferences to give talks. I have never been to a conference before covid. So that was that was all very new to me. So people started to recognize me at those conferences and wanted to take pictures with me. That was that was really something I've never thought would happen. And of course, it's how I got my my current job at Sentry as well, because Kramer reached out to me in a in a DM asking about some collaborations because Sentry as an office in Vienna. And I thought that sounds cool. So we met up with the head of engineering in Vienna. And that's how we started the collaboration where I'm working at Sentry. So yeah, my career would have been I don't know where it would have been, but it would have been totally different, if not for open source. So how active is your involvement with React query? Because I feel like there were and I'm not super deep into it, but I feel like there was like a major version bump last year. Yeah, with some changes. What is the roadmap looking like these days? Are you still actively developing or is it more like in a maintenance mode? Where is it going? That's a good question. So I tried to avoid doing major versions because that always upsets people. It's a very hard thing to get right. It's so hard to get right that I also gave a talk on that topic. Yeah, major versions are something that people kind of look forward to because the library has something new to offer. But that's not really the case because we use major versions to document our breaking changes when we made a mistake in the public APIs. So that's kind of like we then always try to add some features to the major versions just so that they sound good. And this always becomes this marketing event, which isn't really helpful because I would like to do some breaking changes in React query still. There's some APIs that I think that could be a bit better. But at the moment, they are not worth a major version. People would be, "Oh, you're just breaking things, changing things for no reason, removing stuff." I also removed stuff that was bad. It was good. It's a strange still. But the complaints I got for removing the callbacks on use query, that was not something I want to do again. So yeah, right now we're doing some experimental features, releasing them with an experimental prefix because I don't want to lock in the API yet. We have some support for streaming from async iterables that can be used with LLMs and chats and other things that you stream from the server. And we have an experimental feature for fine-grained persistent that works a bit differently than our current persistent where you can write each query to its own entry in, say, local storage or async storage. So those are all things that we're experimenting with API-wise. And then we want to make them stable once we feel we have a good enough API service that we don't need to change it again in the future. But other than that, I have a short list of things that I would like to change. And once they reach a certain threshold of things that are worth releasing a major version for, then we're probably going to do it. But it's not something I'm looking forward to. Yeah, but how is the integration with TanStack start? Because from my understanding, TanStack start is mainly built around TanStack router. But the async state story kind of plays into it too. So how is your involvement into that? Or is it more like sharing opinions, API feedback, those kind of things? Yeah, I'm a bit involved with the router because when I still worked at Verity, we were evaluating a couple of routers. And TanStack router was one of them. And we then built a new product with TanStack router. So I got involved with the other maintainers and also made some PRs, made some changes. We're on a very good basis. And this direct contact on Discord is really, really helpful for that. I don't consider myself like a maintainer of TanStack router or anything, but I do have some knowledge about it. And of course, it integrates very well with React query. But the thing that we should probably know is that the router has its own kind of like mini caching system where you can cache responses from the load of functions that you have. And that works really well if you need data only for a specific route. So if you have like a slash posts route that fetches posts data, and you don't need that data anywhere else in any other pages or routes, then you can just use the router cache for that. And I think it's pretty straightforward to start out with just that. And you can get like an amazing experience out of the box with that. And where query then comes in is if you obviously need like caching on a more fine granular basis and you need the same caches on multiple routes. And I think if you're building like a web application that has some scale to it, then this will happen. But then swapping in React query in your route loaders and using use query instead of use loader data basically, that's what it comes to, is then a straightforward change. So for the router integration, I think it plays really well together obviously. But React query also plays well with other routers that have loader patterns like React router. So those things work really well. And for 10-stack start, I'm not that much involved. But to the best of my knowledge, start is 90% 10-stack router. And then there is like this layer on top that handles server side rendering, server function, streaming, all those good things. And there were some integrations also for queries. So there is a package I think that's called router with query that kind of like gives you a query client that has some default set that can enable the streaming. And we also added a bunch of-- it's not hooks, but it's point in time where the start integration can hook into the query lifecycle. So we kind of like added some of those into the library as a kind of like an undocumented API that start is using to kind of like do the whole streaming stuff. But that's as far as the integration goes. So one thing that I love particularly about the 10-stack ecosystem is that you usually come up with these really cool ideas. You as like a-- Collective. More or less, every 10-stack library is available in any framework. I mean, like I appreciate the maintenance aspect of that and like the effort, the sheer effort that goes into that. But why? Why? It sounds like a maintenance nightmare. Yeah, sometimes, but not really. So I think the whole thing started out-- if I remember this correctly, at least from the query perspective, it started out by accident more or less because we had in-- so in React Query version 3, we had the package name React Query, obviously. We internally, we just had some folder structures. There was a folder called React and a folder called Core. And the core part, this was on purpose, right? The core part was separated from React, but I don't think there were any definitive plans on doing some other adapters or something like that. But then we found out that someone has basically written a view adapter by building a dependency on React Query. So they kind of like they made their own library. They had a dependency on React Query, but they were only using the core. And I found that out because I accidentally broke that kind of like promise that the core wouldn't have React-specific things because actually, I think I didn't know at the time that this was actually important or that it was kind of like the plan. So I put some React import into the core directory and released the version. And then Damian, who is now a VueQuery maintainer, reached out to me and said, hey, you know, this shouldn't be in core because it's React-specific and this breaks my VueQuery thing. I was like, what's VueQuery? That's interesting. I didn't know that it exists. So I reverted that change. But then the same happened for I think the next one was Svelte Query, where the person who made the Svelte adapter, I think they copy-pasted out the core directory and just used the core. So that was fun. And we also knew that there was an Angular version out there that was in the making. So when we made React Query version 4, we said, OK, you know, we can move this over to the 10-stack mono repo and kind of like ask people if they want to come in and use like bring their adapters to like our mono repo. And yeah, except for the Angular part, they were all on board. And the one thing that we wanted basically in exchange is that they stick around as maintainers and they help maintain the adapter and that we kind of like have semi-regular discussions about, you know, what are we going to add to the core? How are we going to support this in the other frameworks? Is there anything that's blocking other frameworks if we design something in a specific way? So those are kind of like discussions that are going on. It's one of the reasons why we have the Query Options API where everything is an object because it's partly like better for solid because they need it as a function. Then they can have like a function that has like the whole object instead of having like multiple things that need to be functions and so on. So those are all kind of like design decisions that went a bit into that. And that's easier if you know the people who are working with this. But if you're all in the same boat, you can kind of like discuss about that. But yeah, the maintenance effort for me personally, I do the core and I do the React adapter. And sometimes I make changes in the core and something errors in, I don't know, solid. And I'm like, what do I do now? I have no idea. So, you know, I need some help from the other maintainers. But that's why we are multiple maintainers. We have at least one maintainer for each framework adapter. And that's very important because yeah, I couldn't do all of that alone, obviously. Okay, that makes much more sense because otherwise it sounds to the nightmare of just like knowing those insets out of all those frameworks is already like. Yeah. But it's also worth mentioning that the most problematic adapter is always the React one. Like it's like. Okay. How so? Because I would have bet money on the fact that it would be Angular. But please. I don't know. The Angular adapter is pretty new. But Angular has signals now. So it's built on it's been totally on on signals. So it's only Angular, I think version 16 and upwards compatible. And that's pretty similar to how solid works. So that's kind of this. Yeah, I don't think there's that much there. No, for for React, when you look at the adapters, right, let's put it like that. Building an adapter is not that hard, right? I've done it on stream where I'm building a lit adapter in the query gg course. We're also building. There's one lesson where you build an adapter yourself. And it's a jQuery adapter. It's called jQuery query. Just fun of it. It's just about you know, you create this this thing called the query observer, and you subscribe to the to the to the query key that you want. And then you have a callback where you get an update in. And then when that update comes in, you need to take this object and somehow, you know, update your UI with it. And in react, that means trigger re render and give that object back to the consumer of the hook and install it. It probably means something else. And in jQuery, I also removed everything from the DOM and just repainted everything because that's the mental model. But you could also just surgically, you know, update some elements or whatever. So the concept of an adapter is relatively easy. There's not much much to do. So most adapters have like 100 lines of code. I think the React adapter is like double that. And the reason is mainly support for suspense and error boundaries, because suspense is a beast and suspense integration is framework specific. So you need to do you need to build that in every framework in React. We currently throw a promise for error boundaries, we throw an error, but React still re renders it. So just that there's some that there's a lot of glue code in between that tries to make sure your application behaves the way you want it to, even though you are going to throw to an error boundary. And then we have experimental support for use. I think that's at least, I don't know, 20 lines. And it's it is we're not really there yet. So, yeah, understanding what React wants, I always get for this, for example, for this use integration, I always get like that there's a bug open where we get an issue and the error message basically says you're supposed to like not pass a new promise to use every time. It's only supported for, you know, you should be using a what's called a suspense enabled framework or library. That's the error message. And I'm like, I'm trying to build the suspense enabled library. Like, how do I how do I do it? This is this is isn't helping me. So I don't know. We're kind of like struggling a little bit with that. That's exactly what my next question kind of leads into because I'm not super deep into the React community. So that might be my bias, but it kind of seems like the reaction comes up with all great ideas that have impact on library maintainers. Like server components is like a great example for that. And I'm often feeling like it lacks the communication path of like to the library maintainers of like, this is what this means for you. This is the impact that it's going to have on you. And it seems a little bit like, go figure it out yourself. Is that an accurate perception or is that just my Twitter bias? Now, it mostly it's mostly accurate. So you should you should talk to Mark Erickson about this. He's kind of like the spearhead of this. Oh, that's a good point. The React community. Yeah. And he has a lot to say in that regard, I guess. I think the gist of it is that we as as library maintainers, we feel that the communication with the React core team is. How shall I put this? The communication with the React core team is not that easy from time to time. We are often left wondering how things are supposed to work. And we've been wanting to get like a tighter collaboration for a long time. For example, at React Summit in Amsterdam, every year there is the, there's the React contributor summit where library maintainers come together and discuss for a couple of hours what the state of the libraries is, any topic that we want. And we've been trying to get like a React core maintainer onto those discussions because it has mostly come down to a, I think Tanner call it a self-help group where we're just sitting there and basically talking about our problems with React that we have, but nobody's there to kind of like really help us fix them. So we sometimes, you know, wish there would be a more direct communication. And I think from what we can settle on is that the best thing we've had was the React 18 working group, which didn't work well for everybody who was in the working group, probably someone who wasn't in the working group feels that they were left out of it. And this is probably the hard part to say, where do you draw the line about people that you want to have a close discussion with and who's invited and who isn't invited? That's really difficult. I understand. I understand that they don't want to play favorites as well and so on. So it's not an easy decision, but right now we have nothing. And that's kind of like we have who shouts the loudest on Twitter. Right. And that's, that's not good. I agree with the part that it's not easy, but you can share objective metrics or something because like you can evaluate the relevancy of a library for the React ecosystem, like remakes or React router, even though it's maybe a direct competitor or alternative to 10-stack router, there's both still very viable options with like huge impact on the ecosystem. So I yeah, okay. I'm a little disheartened to see that my perception is accurate. Yeah. I thought it would be better, but, but it is also kind of what I, I heard from React folks is that they're, they're sometimes. How to put this, but kind of try not to make too generic statements because they were like whole, like their word was hold against them too often. So that they're, I feel like slightly since COVID, I feel like the public presence of the React core team people has been down a little bit to a lot. It's still like a lot of very vocal people in the community. Yeah. Sorry. I only joined, I think I only made my Twitter account like really active when I started to write my blog and there was during COVID, so I have no comparison to how I was before. But I still think that a lot of people are active on, on, on Twitter. I'm not there anymore. I can't really tell on, on Blue Sky it has calmed down a lot. That that's for sure. Yeah. The thing that I'm very frustrated particular with is that the fact that Dan Abramov shares some most content about server components and the impact it has trying to explain the mental model. It's, it just clearly states how big of an education gap there is. If someone who used to work on the React team and just out of passion for the technology shares its relevancy. Anyway, we talked a little bit about there are some minor things that you would want with React for the next major version for React query, but there's nothing that you say, oh, we want to restructure like bigger impact things. Nothing along those lines more like right now is mostly like a mental list of three, four things that you would like to improve, but not like have enough of an impact to cut a new version you were saying. Yeah. So I have a list of things that, that, that I want to change. One of them that, that might lead to some deprecations of current APIs is that we want to, or I have the idea of, I think, I think I've either wrote an RFC about it or I want to write one, but I think I wrote one already about making our, unify our imperative, imperative querying APIs. Because right now on the query client, you have, you have multiple methods to make an imperative query. So we have .fetch query. We have the prefetch query and we have the ensure query data. And in a nutshell, they all kind of like do the same thing, but slightly different. And this is one of the, these scenarios where I get asked a lot like in a server component, should I use this function or that function or in the route loader? Should I use this? Or I've seen an example where you use this function. Why did you do that? And so on. And the answer is probably it doesn't matter. Like 90% of the time, just fetch the data and pass it on. It's like all of the differences between those functions are so nuanced that when you're starting out, it doesn't matter. At the same time right now, you have this hard decision between which of those three things do you want initially. The idea is really to just put them together into a single function called query. And then you have query client.query and that thing acts similar to use query. It's like your one stop shop for getting data, just not in a declarative hook that also subscribes to stuff, but just imperative gives you a promise you can await it or not or whatever, and then go from there. And then we'll find a way to kind of like make it possible to get all those differences in with some options that we have that hopefully won't be too complicated. But those are things that you should, as a user, you shouldn't need to care about this when you're just wanting to fetch some data in a route loader. These are things that you should care about once you get to a point where this actually matters, which might be never. So this is something that forces a decision onto you too early. And I see lots of people struggling with this because the question is real, like which one should I use? If there are different functions, they might have different use cases. I'm kind of like I'm about to get annoyed by those questions because it doesn't matter. Like just do anything. If you don't know that, then obviously you want to know which one is better for your situation. Yeah, this is something that I would like to would like to look into. But it's there is no real like groundbreaking innovation going on in React query because and I think that's a good thing because the library is generally stable. I just looked it up today. It's used by it has 10 million weekly downloads. Compared to React, which has 40 million weekly downloads. So it's like one in one in four is the ratio that that gets used. We're not going to do any any groundbreaking redesigns. Everything that, yeah, that's being used today is probably, you know, in a good place. From the way you're talking about those things, it seems I get the feeling at least that you're very close to the community and I get it from the way you came into the open source space. But it's not covered anymore. I assume you have other stuff to do as well as is it just the fact that you're terminally online as some of us or how do you strike the balance between like, OK, gather the community feedback, see where issues in the library are, but also like keeping up with regular maintenance or how do you yeah, how do you strike that balance? Yeah, so if you ask my wife, I'm probably like always online and doing stuff. So this is kind of like I have a family, I have a job, I do open source. It's it's a balance that I have to strike and I'm not really good at it. I also like sleep. So that's that's some things you have to have to cut corners somewhere. And I've realized that it shouldn't be family and it probably also shouldn't be sleep. So I have to cut corners somewhere else. I am only working part time for Sentry at the moment. So I'm doing between 20 and 25 hours. This is this is only possible because of of the sponsoring that I'm getting for my open source work, because the course that I made on ReactQuery, query.gg generates some income from me that allows me to take 50 percent of my time to devote to to open source. This wouldn't be possible if I needed to work full time, because then I probably wouldn't have any time left to do open source. But as it as it stands, I can split my day into four hours of paid work for for Sentry and take some time in between or afterwards or before to really look at Discord, look at GitHub, still subscribe to every issue and discussion. I'm still pretty fast in responding to things. I really want to look at every issue and discussion right now. I have it's just 40 unread emails on ReactQuery stuff that I need to need to go through. Yeah, I just came back from vacation. It was like 250 or something and more than work emails. And that's after I cut off all the bot traffic. So that's that's like real real humans that the right stuff. But yeah, this is the the the prime primary factor is that it is part of my work now. So I'm not a full time open source sorcerer, if you will. But I'm doing it part time. And yeah, this is possible because I do get some some some pay for that. That's awesome. It's the context switch taxing on you in a way, because I I assume I mean, we talked a little bit this before hitting the record button, but I assume the Sentry code base is pretty big, too. And then your role, we will talk about that in a little bit. You also need to have somewhat the overview of like a little bit of everything. So I assume just like from a context switch, this is like a lot. Yeah, that's interesting because I love context switching. I think I'm the only person I've met or like I don't know if there are lots of people say that they don't like context switching, but I'm I think I'm quite good at it. And and I love it. I've I've when I worked at Verity, I also was working as a tech lead. So I wasn't working with a specific team, but I was working with up to 30 people in five different teams. And I was always like scanning the the Slack channels, always trying to be on top of things, getting an overview and then diving deep into into something and then going back to a higher altitude and viewing things again. I also have some some some projects from I think 2017 that I'm still maintaining. So does that sometimes get some get some things that I need to look after. So I'm I'm really switching a lot and I don't mind it. I think it's it keeps me, I don't know, involved. I think I'm fairly good at context switching, but I've never never met anyone that says I love it because I always feel like it to some extent when I do it a lot, I notice like how I feel like very productive for a very short time because I feel like I do a million things. But then like after I don't know, in particular, my role, it's often like different Twitter conversations or those kind of things. I feel like after an hour, I'm like, oh, I'm so tired. Shoot me in the face right now. So I don't think I could do that on like that scale. That's really impressive. Do you have any tips that you can share with me or just suck it up? Well, I think I I don't know, maybe I just get get bored easily. So I need to switch between things a lot. Maybe that's it. I also really. Even though I just said I have 40, I really like inbox zero, so I'm always working towards that for for slack notifications. That's like a big thing for me that I've always kind of like read everything or at least acknowledged everything or put it on a different list. I can't just have like a million unread, unread things that I'm because that I'm never going to look at. Other than that, I do take lots of breaks, I think, in between. I also like deep work, but I haven't done a lot of it in like in a longer time. So like really going eight hour deep focus on one specific problem in the zone, headphones on no communication left and right. I do that with writing, though. So this is when I when I was working on the on the on the course, I was also doing that two days a week. And on those days, I really turned off all the other apps on my on my computer. I was really offline in terms of like for everybody else, because when I'm writing, I need the concentration for that. I don't know for coding or for for solving problems like when I'm solving a tough problem, I'm stepping away from the computer anyways. So I go for a run or I go for a walk. Or I kind of like I do so much programming in my head that it's kind of like that going to the computer and actually doing the typing. It's kind of like at the time, it's it's it's boring because I solve the problem already in my head. I don't know if that's if that's typical or something. But yeah, I just I just do a lot of think a lot of thinking in my head and I I rarely turn my head off. That's that's not a thing. That's interesting, because when when I interviewed Ryan on this podcast, he shared exactly the same same story that he's like he had this analogy of like saying he he fears that he gets hit by a bus one time because he's like out on a walk and it's like thinking about a problem. But the actual coding part then just happens like two hours at night when the kids are in bed. Kind of like. Yeah. Yeah. I think that's really interesting. I want to say that's what the actual nerd sniping comic comes from. Yeah. So I would like to talk a little bit about your role at Sentry, because you shared with me earlier that you're working in like a front and platform team. And that's a more common role for like big teams like I know Google has that for programming language, for instance. This is not so much a thing for smaller teams. So I would appreciate if you can share some light what you're actually doing, how you're measuring your productivity and those kind of things. Yeah. So I'm part of the design engineering team now. And one of our one of our it used to be front and platform team. Now it's not an engineering team. Doesn't really matter because we still do do the same thing. And what we do is we try to make it easy for teams that actually work on the Sentry product to ship things efficiently and to ship the right things. And that is an important part because the Sentry code base has grown over the last 10 years. And they were mainly consisting of product teams where everyone was shipping parts of the product that they were responsible for. And a lot of things have been reinvented in all of the teams. And when you when you have no one that actually looks over the architecture or looks over how things should should be implemented, how things should align with each other, then you kind of like get to the situation where things start to crumble a little bit. Yeah. When I when I joined Sentry, I also said that, you know, this team would have probably been a good idea a bit earlier, but it's never too late to start it. So it was started when when I joined in in January. It was actually the plan to make it was before I tried. And then it turns out that I'm a good fit for the team. So I'm really happy that that I found that home in in that team. And yeah, as the Copis has evolved, we do have a lot of work ahead of us. But right now, one of the main things that we're doing is this was one of the things that we figured out was one of the biggest pain points for people is that like we have a very big components directory. And it's you don't find anything in it because it's it's so big. So what we the first thing that we are or that part of the team is working on is going to extract the things into its own design system and try to give people good primitives and good interfaces and good APIs. Because some of the some of the APIs also have evolved where people edit their own like flags to it because they needed it to work a little bit differently for the use cases. And, you know, if everybody just works on what they think is important and what they want for their specific use case, you get like APIs that are probably not good for anybody. And then somebody finds it and says, oh, I'm just going to build my own version of this. And all of a sudden you have like three select components or five form abstractions or whatever. So it's kind of like at at that point, it's it's a good idea to kind of like have a team that really owns this topic. And that's that that was the missing part was like the ownership of a design system, but also an ownership of an architecture, how things are structured, which things are which constraints do we want to set. And so on. And this is also one of the things that we want to work on. I get the concept of that team. But how do you prioritize your work? How do you how do you manage that aspect of like, do you just exaggerating? But do you just look through the code, see some smelly code and be like, oh, let me fix this today. And along the way, you saw something else and then that for tomorrow or because I assume there needs to be some oversight of like prioritization and et cetera. Yeah, so we are a quite small team now with four people. And we're also relatively new. So the whole team only assembled like beginning of this year. And then a couple of people still had to do had to finish up their product work. Yeah, we're still very new and trying to figure out what is most important and what is the what is the process that we want. But right now we just everything goes so fast that we just come together on a weekly basis and we decide what's the most important thing we want to help people with this week. And then we're going to make a plan and then we do it for this week. And then the next week we see how it went. And then obviously, you know, things come up in in in the meantime, like, hey, you know, TypeScript just got 10 times faster. Maybe we should try out this TS GO thing and see how this improves for everybody and so on. So there's always kind of like little nudges from the outside that come in that kind of like shift our priority a bit. But the big goals are building a design system with good APIs and abstractions starting from, you know, layout components is one of the biggest things that people have been missing. So they've just been, you know, been applying different stylings and different ways of defining layouts all over the code base. And we can make it a lot easier. There are so many. I don't want to say low hanging fruit, but there's so many big topics that once we tackle them will hopefully make a huge difference that, yeah, we are we are very focused on those first. How is the communication with the rest of the developers going that because that seems to me like a little bit of a challenging task if you have like, OK, you identify we have now we have an issue with layouting, right? So you add various layouts, et cetera, you introduce them to the code base. How do you make sure that everyone is aware of those and how do you make them sure that those petals gets applied correctly? That's actually the hard part. It's a good question because communications with with with other humans is even in technology. This is this is the hard part. What we do and what I've also done in the past that variety is we try to be very upfront and very over-communicative with the things that we're doing. Sentry has this internal blog platform called Shipped Posts where you can write an entry about what you ship that everybody is encouraged to read and see about. We have multiple channels that are related to the front-end platform where we post announcements and things that we've done. I also want to do like more also external documentation on the topics that we're doing. What I did before at Verity was short videos about how what we've done, how things work, what are good patterns, kind of like these educational knowledge sharing style, two minutes maximum because attention spend videos that people like. People like that better than a one-hour session on how to use query correctly or whatever. That was kind of like that was that was too much. But short videos is something that people like to consume. So that kind of worked well. And yeah, then it's then it's all about knowing the teams, what they're building and also staying in touch. Sentry also has like a very extensive system of code owners. So you do get pinged on PR when something changes in the APIs that you're having. But of course, to see if things are being used or if something is being misused is something that we need to probably iterate over and see what is the adoption rate of components and so on. Also, I think one thing that we could also think about is introducing some kind of boundaries and lint rules and other things that kind of like nudge people in the right direction per default. So that if they find out that they are maybe wanting to override the styles of a button with a style component, which they can do in their part of the product, then maybe there's going to be a lint rule that tells them, hey, that's not the best idea. You can use something from the pre-built components that we have and so on. So I think tooling is also something for a developer experience that we will look into doing. Again, before we hit the record button, we had quite an extensive chat. So I have a lot to go back to in this sense. You brought up the fact that one thing you recently worked on was integrating Knip, which I think is a fantastic library, heavily underutilized and people should know more about it. So I'm happy to feature it here. And its big selling point is basically finding unused files and unused imports and all those basically everything that is unused. How much was unused within like a big code base like Sentry? Oh, so much. So I also prepared a talk on that topic because the journey was really interesting and it started basically with me adding, I think the final nail in the coffin where I said, OK, now I need to remove all this dead code in an automated way was when I was adding the ESLint rules for the ESLint plugin query. That kind of like so it's it's it's already is lint plugin from React query that kind of like tells you when you are using, for example, something in the query function is not part of the key, which can lead to problems. It tells you about some other things that you that you should be doing. Just some basic stuff that I think everybody else should be doing. So, you know, it's it's a good thing to to use the lint rule. But when I added them and I had to kind of like there were some violations, I wanted to fix them. And then I found a custom hook and looked at it and I was like, OK, I need to like change something there. Where is this used? And I was like, this is not used. Like I'm trying to find where this is used. And I didn't. And I spent at that time, I spent like half an hour already trying to, you know, fix this thing. And I was like, OK, this this can't be it. Like how much code have I touched that's actually unused? Kind of like I don't even want to know. So I tried to bring in Knip. It took some time. I made a couple of PRs. And at the end of the day, I deleted over 20,000 lines of code, which is I think I think that's almost like a fully vibe coded application these days, right? Twenty thousand lines. You can do a lot of things. But that was I think there was a big win because that's and also removed some some dependencies that we had. I think that was like some some charting library that was only used in an unused component. And the good thing about Knip is it it goes further than just unused stuff. So if you have something that is used by a test, for example, you can find that because the only thing that it does is it kind of like it tests itself. But it's never used somewhere in the things that you ship. Or if you have like storybook and you have a story for a component, this component will never show up as unused because it's used in a separate file. And that's kind of like not going to be deleted by anybody because it shows up as used. But it's not used in a way that gets shipped to the product. So I also deleted a bunch of tests, obviously, for components that had tests that were unused. So there were lots of like lots of good wins in that initiative. Yeah. And also the dependency part is the thing that I was super surprised at, because figuring out what libraries I use is so difficult from like just a module resolution perspective. Yeah. So that was just one thing where I was like, every project is more than a year old needs this. Yeah, because if especially if a strategy is you go through and just update all the library, finding out where they are used and what impact your update has, it's even worse if you know that you need to update the library because you need it in position A. And then you see this dependency is also used position B and then you have no idea what that is. If that thing is unused and shouldn't be there, you know, you don't have that problem. So, yeah, and we now have running in CI. So every new PR gets checked about if there's anything left behind, because that's how most of the dead codes are. You know, nobody writes code that is dead and never used. Maybe in some situations we did that for a feature that that got deprioritized that never made it. But most of the dead code that we had was because someone wrote some things and then they were removed from the one page and then they were removed from the other page. But the actual component or util function or whatever, the last usage never cleaned up the whole implementation after itself and combined that over 10 years and, you know, fast feature iteration. We built this feature at POC. We tried out. No, we don't want it. We built something else. If the thing stays behind the whole feature or parts of it, then this accumulates really fast. Was there any feedback from the development team on that particular change? Because like if I do, I don't know how long you were in the company at that point, but if I see a PR from someone who joined recently with like 20,000 lines of code, I would be like, you sure about that? Yeah. You sure about that? Yeah, it wasn't it wasn't one PR was over 50 PRs. So I tried to trim the PR down to to only affect a specific set of code owners, because if you touch every that was kind of like that was my first PR that I made where I made that mistake. My first PR I touched 900 files because I think I joined in January and like a couple of days later, I opened my first PR that touched 900 files and that added no implicit any TypeScript compiler setting that was set to false for some legacy. Historical reasons I said that to true. And yeah, so we had to touch like a lot of files. And then I saw I pinged like the whole company basically with the code owners. I was like, it's not very likely that you will get the review because nobody wants to take responsibility for that. And it's better to split this up into smaller things. Of course, with a central setting like that, it wasn't possible. But for Knit, I really tried to break it down into codons and made multiple PRs. So that was good. But the difficult part was was still to get people to accept the change because at some at some point, it still influences how people work. Right. There was there was one thing that not really doesn't allow it, but there was this this tendency to make a PR that adds a component and not use it anywhere because we are going to use it in the next PR or maybe in the PR after that. And then obviously you are adding from from from from the tools perspective, you are adding that code. There's there's no way to distinguish this. I mean, you can't predict the future that this will be used. You're adding something. It's unused. You can't do that. The better way, I think, or what we've agreed upon is that we're going to build features in like the full vertical then so you can add a feature flag. You can put it behind a feature flag toggle, put it in the UI and then make a PR and merge it. Maybe just do a little bit of a skeleton for that feature. No user will see it anyways and then go from there. But it's still kind of like it influences how people work. And whenever you influence how over 100 people work, you know, you need to get the communication right. As you said, you need to get people ahead of things. You don't want to surprise anybody comes back from vacation, sees this new failure, doesn't know what it does. Gets aggressive, maybe a little bit, maybe a little bit agitated about like, why is this thing not working? So it's all of those human interactions that are that are always the thing where you have to be really careful and thoughtful about that. Interesting. But once those problems, let's face it, were squared away and the merchant to the Sentry Code base, did you notice like a positive impact? Even if it's just like feedback of people noticing and improve and perceive quality or because that's the thing that I would kind of struggle with if I was in your position is like, OK, how do I value the impact that I have? How do I measure the impact? It is definitely easier to measure the impact when you're working on the product directly. And at Verity, the where I was working on on a similar team, we were always we always had to have this saying that we are kind of like our success is basically measured by the success of the other product teams. So if the other teams are happy, if they can ship fast and error free and efficiently and things like that, then then, you know, the platform team is doing a good job at enabling them to do that. In in regard of the of the of the Knip situation, I generally take no negative feedback as a positive. And that is I think that's usually as as much as you can can hope for, because I think people I think people should come. Actually, I think people should complain more and they should complain about things that they don't like and not just suck it up and say, yeah, this is the way it is. Because if if teams like our team don't know about the problems that they exist, we can't make them better. And even if you are, you know, even if you are a little bit agitated and say, you know, whatever you did here, this sucks, it breaks my workflow, whatever, everything breaks somebody's workflow. That's kind of like how it is. But not knowing about the problems that people are having, that's that's even worse. So I always encourage people to, you know, say the things how they are. If something's not good, we are hopefully going to make it better. Initially, I did look up at the some of the PR checks to see how often was Knip failing in CI. I saw a failure in CI is a good thing because it means it caught some leftovers that somebody forgets, forgets to remove. And then I think like a couple of days after I enabled it in CI, I saw a PR where something was removed, but there was a leftover. And then the next commit basically said something like make Knip happy or whatever. And then it had like 100 lines of code additionally removed. I was like, yeah, that's that's a good thing. You know, this this CI failure, maybe it slowed you down because you had to look at the error, go back to your code, remove that stuff, commit it again and so on. So that's it is a bit of a slowdown, maybe at this point in time. But if everybody does this, yeah, this this really pays off. Having 100 additional lines of code that add mental load that needs maintenance and those things. So having them removed if they're actually unused is a very net positive, even if it feels like you're a slow down five minutes. 10 minutes in that moment. Long term, great investment, even mid-term. Yeah, cool. But what I'm curious still, how was the process for you? So you said you kind of went like in a very iterative approach where you said like one chunk of the code based by chunk. Did you feel like at some point overwhelmed by the amount of effort? Because that's how often how I feel when I do like infrastructure work where it's like you tweak one thing and then you know, just like, oh, you also need to tweak the other 13 things. So I feel like with infrastructure work, it's always this mountain of work that you're pushing and you sometimes fix a little bit. But then you notice, oh, there's more things to do. So yeah, how did you structure your work there? I remember being excited when I got to when I got to like zero violation on my my my things and I merged all the PRs and then I went to sleep and I came back like the next day and because Sentry works a lot in the US When I get up, you know, people have worked for it out and I pull, I don't know, probably like 50 commits, 50 PRs merged from master. And I was back to eight new violations that just got in because the check was not it's like, I need to start again all over again. So, yeah, the speed and the velocity of how often gets committed to Sentry is is a lot. And at that scale, yeah, sometimes you think, oh, this is just a little change. I just need to do this. And then you kind of like go into a rabbit hole and discover all all all other sorts of things in there. So, yeah, that is that's part of the of the challenge. But I like it. But I can very much resonate with what you mean with like different times and stuff. That was one of the big things for me also when I joined JetBrains before I did like a lot of consulting with like maybe it's like two or three different teams, maybe like 20 developers or something out of nowhere. You have like 800. It's like the scale difference of like teams with like three developers to like twenty hundred. It's always so different how you need to structure your work and the things you need to consider. I was very impressed by that. I'm very surprised, positive and negatively. I am still adopting a little bit to the the times on difference, even though there are people in in Vienna, in the Vienna office, they're not directly on on my team. But I work with them on a on a daily basis. So so so that's good. But, you know, when there's really something that I need from from my team, I need to wait until the afternoon. So that's just something that that has changed for me. And I've just shifted my work a little bit more to the to the afternoon and take some mornings off for a run or something. Yeah. So, Dominik, thank you so much for joining me. This was a great conversation. I love the nuanced takes you have on like the things you see in the ecosystem and how considered you are about your approaches and particularly how connected you are with the community. I really appreciate you. Yeah, thank you for having me. I had a great time. Good. Glad. And I really hope to see you back on this. So if you want to be back, just let me know if you have my number in any various ways. Absolutely. Thank you so much. Looking forward to it. See you next time.