PodRocket Faris Aziz - Audio Edit === Paul: [00:00:00] Hi there, and welcome to PodRocket, a web development podcast brought to you by LogRocket. My name is Paul, and today I'm joined with Faraz Aziz. We're gonna talk about caching, payloads, and as we're gonna put,~ uh,~ somewhere in this podcast, other dark arts. So welcome to the podcast, Faraz. Faris: Thank you so much. Really excited to be here Paul: ~What, ~what are dark arts? ~What~ Faris: What are dark arts? ~All, ~all the front-end trickery that we've gotta twist in to make something work, basically. ~Uh, ~when everything around the front end, the back end, the infrastructure, the stuff's just not ideally set up, what are the things that we can twist in the world of the web to get the solution where we want it to be? Paul: So we're gonna talk about data, right? ~And, ~and requesting things that might otherwise be hard to request, and I'm guessing tying it all together is in of itself a dark art, even if it's just using it on the front end Faris: 100%. ~It's like, ~I think the overall theme is like how do we create optimal user experiences in suboptimal [00:01:00] conditions? Paul: What is the suboptimal condition that we're talking about? ~Like, ~what are you guys cooking up over in the Fyrus lab? Faris: So this was like a problem space that I experienced three years ago at a fintech where we were at, working in a super high-speed startup. ~In very, ~in very typical startup fashion, you've got a front-end team working, you got a back-end team working, and the priorities are almost never in sync. And when we were developing,~ like,~ an API-first product, naturally the front-end's got to integrate whatever APIs are available that are also being given to partners. Similar to,~ like,~ Stripe. Stripe's got their own APIs that we all get to consume and use from, and they can't just update those willy-nilly. Their Stripe dashboard has to also internally consume those APIs. And so when I was building this fintech dashboard, I had to work with a limited set of APIs to get things working. And so ~this, ~this talk ended up just evolving, getting a little bit crazier over time, to the point where when I presented at, presented it at React Summit New York,~ uh,~ last year in November, that suboptimal condition I really wanted to test was I filmed,~ uh,~ or recorded all the [00:02:00] demos of the solution on the flight from Switzerland to New York on the network conditions of the plane to be able to see does this stuff actually, does the theory actually hold up in practice. So the Firehose Lab is just cooking stuff up on a plane 'cause I'm always traveling everywhere. Paul: So you were cooking up,~ um, a, ~a demo for a fintech dashboard Faris: Yes. ~So, like, ~imagine if you open up your Stripe dashboard,~ um,~ you've got to see a bunch of transactions, right? I made X amount of money every single day, and so in a similar fashion, I was building a fintech dashboard at a fintech company I was working at, where if I logged in as a user, I had to display transactions that were made. And let's say we had to display transactions for the last three days, seven days, and 30 days. And we assumed, because we did not have enough users at the time, that,~ like,~ you're not really gonna be displaying more than 5,000 transactions, so your 30-day view, we would just request up to 5,000 transactions. Now, where things got problematic is [00:03:00] that you naturally have SLAs when it comes to building an API first product and you gotta abide by those service level agreements when you're selling a contract to another company and you're like, "We're f- they're paying us money. This thing has to work at a certain level from a performance perspective, reliability, availability," so on and so forth. And so when we had to query for our transactions API, we, there's naturally a limit. Like, how many can I request? Can I request 1,000, 2,000, 3,000? And we wanted to request 5,000. The problem really here was, is that the limit was 1,000 at a time. We could not request more than that, and if we went to the back end team and asked them, "Hey, can you increase this limit for us?" We'd break the SLAs because the queries at the database level or something else weren't performant enough to upkeep at anything beyond 1,000. So what is that first dark art that we employ? We gotta make five parallel requests on the front end, and that's where all the fun starts, 'cause now you start introducing five points of failure. So that's where it really comes from. Paul: ~Right. ~Okay, that definitely paints the picture for me [00:04:00] and,~ uh,~ the problem that you were faced with. So when you went and took the pencil to the paper, is this something that you felt was net new in your career arc of having to facilitate,~ like,~ this paralyzed front-end cacophony into something that made sense? Faris: At the time, y- a little bit yes, right? Because you're seldom cooking up solutions in isolation when you're working with a team. You gotta get buy-in. You gotta figure out,~ like,~ okay,~ um,~ you're first gonna argue, "Why can't the back end make this change? Why aren't you fixing things at the database level?" ~Like, ~"Why is the front end compensating first?" ~Right? ~So you're more dealing with architectural conversations to make sure that you're implementing the right solution than the back end compensating for the front end and vice versa, or the front end compensating for the back end. You seldom wanna do that, but you gotta be pragmatic at some point, and you gotta be like, "Okay, the front end's gotta maybe implement this [00:05:00] for a month or two months till the roadmap aligns, and then at some point we'll have a data warehouse or another endpoint that gets us where we need to be." ~Uh, ~long story short,~ that,~ that, that solution was in place for two years, and I don't think that would surprise many people Paul: No, ~of~ Faris: everyone's like, "This is a temporary fix," right? Paul: ~Of course, ~of course, the temporary fix Faris: Yeah. ~That's, ~that's ~the, ~the legendary temporary fix. ~Um-~ Paul: temporary fix fixing right now? Faris: It held up pretty well, actually. It held up pretty Paul: Let's go. Faris: ~Um, ~and I faced things now working at Smallpdf that are almost the opposite scenario, because this was a startup that had very few users, and those were large enterprise users. You were connecting with,~ like,~ merchants,~ uh,~ that ha- were payroll providers to be able to, ~you know, ~make large transactions for salaries or employer of record or so on and so forth. So you don't have that many users, whereas at Smallpdf we got upwards of tens of millions of users per month. So the strategies you employ in one place to fix the same solution you cannot employ in another product, which is ~really, ~really interesting. Maybe we'll get [00:06:00] to that a little bit later on. ~Um, ~it held up pretty well because there's a lot of magic you can get done with TanStack Query, and that's really,~ like, the, the, ~the crux of it. ~Um, ~and there's TanStack Query and also,~ um,~ just being able to leverage Next.js API routes to be able to implement a backend for frontend pattern or a proxy to be able to at least have something that's managing,~ uh,~ aggregating all the data or getting it in the format that you want to. Because whatever the frontend needs to process or you whatever you wanna put in your client state is not necessarily whatever you're receiving from the backend, and we were receiving ~massive, ~massive payloads. So every single object within this array of 1,000 items that we were receiving had,~ like,~ 50 key value pairs, and all we had to do, display was a chart. So a lot of those key value pairs were going to waste, and we wanted to cache that on the frontend too, so we're not gonna take the entire thing, digest it on the frontend, do all the mapping there, and then cache that. Because I think where we landed was a place where we had, I don't know, 1.5 or 1.6 megabytes worth of payload, and that was just these one set of [00:07:00] widgets. There's a bunch more stuff you're requesting you wanna cache on the frontend too, and most caching strategies for offline cache are using local storage, which is gonna run out at some point, right? Paul: Right,~ Right, right. ~So ~the, ~the moving pieces here involve Next.js, TanStack Query, creatively somehow proxying. You're-- You guys are gonna be requesting data, putting it in the right spots, and I'm sure there's challenges, like you mentioned, that we'll get into. Before we talk about anything super deep and technical, anybody listening, we can also now,~ uh,~ Faris mention the conference ~or, ~or the talk ~where, ~where this,~ uh,~ first came out. So where can,~ uh,~ people find that initial talk that you gave? Faris: So weirdly enough, the f- this is the first talk I ever delivered in my conferencing or meetup career, ~and it was back all the way... Well, not all the way, but, like,~ it was in February 2024 at a React Advanced London meetup, and back then it was called,~ um, uh, ~TanStack Query, Next.js, and Your BFF,~ like, uh, ~for back-end, for front-end. And weirdly enough, I also could not get into conferences because of the title of that talk, 'cause most of the [00:08:00] conferences going there, they were like, "Wait, there's already Tanner and Dominic speaking at that conference. We don't need another TanStack talk." And so I was like, "This talk's not really about TanStack." And we had to evolve from there. But it's been at 14 conferences since, I believe. I presented it also this week. So if you just go to my website,~ um,~ fazeez-dev.com, or just put Faraz Fazeez in Google, there are plenty of recordings out there of it. It was at React Summit,~ um,~ in New York and a bunch of other conferences with different variants and different lengths. ~Uh, ~so there are plenty of ways to enjoy it Paul: And you guys also won Community of the Year, right? Faris: Yeah, that's for Zurich JS. Yeah,~ the,~ the community that I run. We won,~ uh,~ Community of the Year around about last month at JS Nations. That was ~really, ~really cool, and we're not even two years into having built this community Paul: Incredible. Okay. And if people wanted to check out that community that you're involved with,~ uh,~ would that be Faris: ~Yeah. Zurich,~ ZurichJS. And there's ZurichJS Conf happening September this year, and we're flying in some pretty cool people, have an awesome after party at the lakeside in Zurich, and there's a lot [00:09:00] of great stuff going on. Actually, I think that there, we have, like, four or five TanStack team members coming. Dominic's speaking on stage and running a workshop, but,~ like,~ a bunch of the TanStack folk are coming in any case. It's even an offsite for some open source folk to come over. Paul: Oh, incredible. Faris: Yeah. Paul: okay. ~Well, if,~ so if you're interested in hearing more from Faris, those are some places that you can go check out. ~Um, ~go check out Zurich JS. ~Um, ~and now we're gonna get back to diving deeper into what we were talking about. Yes. So ~where, ~where did this first, ~uh... ~W- where would you like to start, Faris? Is it-- Do you think the best place to start explaining how this creative caching and request works is with TanStack or Next.js from a perspective, or neither? Faris: It's-- I find it interesting how we lean on the technologies being used when what I love to express things in is being framework agnostic. 'Cause whatever we're gonna talk about, you can do in Nuxt, you can do in Astro. ~Uh, ~it just so happens that I'm experienced in Next.js and [00:10:00] in React, and so it's the easiest way to have employed those things. So nothing's really restrictive here, and the only way to do it is Next.js. But there are actually some,~ uh,~ things that we might talk about a little bit later on in terms of the app router and how ~this, ~this journey started on the pages router, but in the app router, there's some really cool things, especially with the Next.js six point... sixteen point three release that you can employ to even take these solutions further. But let's,~ like,~ start at the bare bones, right? ~Like, ~you need to fetch some information. You need to make five requests. ~Let's, ~let's take all solutions and libraries out of the, out of play, and just assuming you have a bare React,~ uh,~ application, you're gonna make a either Promise.all or Promise.allSettled multiple fetch requests on a client side. And let's say maybe you just throw that in a useEffect. Let's just say that. Now, David K. Piano, if he's listening out to this, he's gonna say a couple of things about useEffect. ~So, uh, ~we're not gonna keep that as a long-term solution, but that's generally the first place you're gonna place some network requests if you start starting out a React application. And that gets-- tends to get pretty problematic, and the way I demo this in, in, ~in the, ~in the application is [00:11:00] very rudimentary, in a very rudimentary fashion with almost a light mode and dark mode toggle, which in most applications is done with a context provider you set at the global level of an application, and you just flip a switch here and there. And sometimes the problems that come with context providers is that you have then all the children re-render, and it could be that you just then have a remount of a component that has the useEffect that makes the five requests, and you're getting into a place that when you're trying to fetch non-stale data all over again, you're unnecessarily querying a server, right? And so the conversation starts with, "Okay, how can I un... How can I only fetch information when I need to?" This is the beautiful model that TanStack starts to present, what it has just in-memory cache from the get-go, right? And so plug and play that stuff with a useQuery, and you're already in a pretty good place, and you've got resilience patterns baked into that solution. So there are easy ways to do multiple queries with [00:12:00] the TanStack Query. You've got the query keys for caching if things are gonna switch up a little bit with the query parameters. And then you've got all the state management managed for you. And then you've just these different levels of resilience where you can do the three basic retries, or generally what's recommended, the exponential backoff, and then you take it a le- layer above, which is then adding those jitters to avoid those thundering herd problems that funnily enough were caused, for example, by the useEffect in the September 12th Cloudflare outage, which is a fantastic article to read because Cloudflare has the best,~ like,~ postmortems ever. Paul: I actually did-didn't even know that. That's fascinating. Faris: ~Yeah, ~which was funny 'cause when I gave this talk at React Summit New York, I think Cloudflare did have an outage, and then David K. Piano tweeted, "Hey, is it useEffect again?" Which I don't know if it was that day in November, but yeah. Paul: a lot of those things with,~ uh,~ TanStack Query,~ I,~ I just take for granted at this point in terms of the query caching and, like, all those things that you had to, like... You're like, "And this and this." I'm thinking in the back of my head like, "Oh, wow, yeah. All those things are [00:13:00] existing and working for me," and I,~ uh,~ sometimes I don't even think about it. ~And, ~and it does get you really far. ~Like, ~you can serve most table stakes experiences,~ I,~ I would say w- with just TanStack out of the box, maybe adjusting some of ~the, ~the TTLs ~on, ~on different queries and such, right? ~Um, ~so ~where, ~where did the line get drawn where you needed to reach for something else? Faris: So I'll tell you even s- before even going to that, something interesting where we take things for granted with TanStack Query is that you have that query cache that exists where if something is not stale yet, it's gonna just... If there's a re-render that occurs, it's just gonna go and reach for the freshest state that it keeps in its cache, and so it's gonna render that. Where I demoed this in the demo application where you have this toggle for light mode or dark mode, which with the context provider showed, meant to show this example that refetches occur, can even have TanStack Query almost compensate for incorrectly setting up your state management architecture. Whereas even if something re-renders just because you're using a [00:14:00] useQuery and it gets something from the cache, you're not triggering unnecessary those use effects that you may have because of referential updates that would have occurred,~ uh,~ from the dependency array. ~Um, ~but yeah. So where do we have to fetch for something else? Now, you're making five requests. Every additional request you're making is a point of failure. So what happens if one of those five requests fail? Now, do you re-request all of them? Do you manage the individual one that's requested ~that, ~that, that fails? Do you have a global loading state, so you wait for all five to complete, and then you aggregate them? And that's where you start getting into UX challenges, and that's where we talk a little bit about,~ like,~ response,~ uh,~ response timelines. And there's this really,~ like,~ good excerpt from this,~ uh,~ book called Usability Engineering, and maybe we can link it somewhere, where if something renders or loads within 0.1 seconds, the system feels instantaneous, but the second it takes a second or longer, that's the limit for somebody's flow of thought. And especially in a workflow-oriented experience where you're clicking through stuff and you're moving and dragging and dropping, you... The second something takes longer, you [00:15:00] start to think, and it's like, "Ah,~ I'm, I'm, ~I'm out of my flow of thought. I'm out of my process. I'm thinking more about the UI now and what's going on. I have to reset myself that I am thinking about the intention I have or the task I wanna complete." And you never wanna get a user there. So generally, if you have five pretty bloated requests, it's rare you're gonna get yourself in a place where that's all loading in,~ uh,~ under a second. And so when we, when I tested this on an airplane, that first initial solution, all five requests on the client side roundabout loaded in 13 seconds. Very painful experience. ~Um, ~the only time I think you're waiting for a website to load 13 seconds is if it's a government website or you need to get a visa done of some sort, or you have,~ like,~ no choice but to use that experience to be able to get what you need to get done. Any other application that you're using where you have an alternative, you will go to that alternative, and that's where you're gonna lose people to your competitors. ~Um, ~so then I'm like, "Okay-" The back end can't really deliver me something that I can use easily, so with Next.js I can [00:16:00] spin up an API handler really easily. And so what can we do there by moving these five requests somewhere else? Now we're spinning that up in a function as a service, and we're just taking that promise.all, promise.all settle, we're moving that over to the proxy level. How does that now realistically change things? And that's where you start to understand a little bit more about networking. And we talk about also this 14 kilobyte rule that you may have heard at some point, which is,~ like,~ if a network request is under 14 kilobytes, you're requesting a website or a resource under 14 kilobytes, it resolves much faster than something that is of size of 15 kilobytes, and that's just because of the limits of an initial congestion window that exists with a TCP connection, right? Paul: back off and all Faris: Exactly. ~Um, ~and so 14 to 15,~ uh,~ kilobytes, ~I mean, ~when I was reading about it, it was around, it could be a 600 millisecond difference, but 15 to 16 kilobytes could be just a couple of milliseconds, and ~that was, ~that was a crazy thing for me to understand. And I was like, "Okay, now everything in the world has to be under 14 kilobytes." And this is bit [00:17:00] of an obsolete way of thinking now because now w- with Cloudflare or modern CDNs, 14 kilobytes doesn't apply as much. I've seen that in different infrastructure setups it can be 46 kilobytes, or it's very individually tested based on what you're dealing with. So the goal now is not to reduce every single payload to under 14 kilobytes, but we can now start doing something interesting where I can take that much larger 1.6 megabyte payload, take it to a proxy. I can now condense that and aggregate that into something that I just want to send to the client to render the chart, nothing else. I don't need any transaction information except how many transactions were done in a particular day, and that's pretty easy. I just have the date, and I have the number of transactions. So it's a pretty lean response, and we managed to bring that around about, in the example, to 300 bytes, so even way below the 14 kilobyte limit. And so we already brought ourselves to a place by moving it at the proxy level while I was in the airplane to have the whole thing load [00:18:00] in five seconds, which starts to get pretty crazy, 'cause I'm like, "I'm still making the same requests. I'm on an airplane. I'm still somewhere in the air. Maybe I've moved a couple hundred kilometers somewhere, but I have half the loading time." And so that maybe is a dark art, that just knowing where was the right place and the right tools to use to make that request. You're not getting rid of the problem entirely, but you're starting to think more at the infrastructure level how that's set up. And that sort of expands your horizons from a front-end engineer perspective, 'cause y- we often as front-end engineers just limit ourselves to the scope of what we work with. And I like to think more of,~ like,~ if you're a front-end engineer, you should have front-end expertise but full stack awareness, just because you don't have a back-end point, right? Paul: especially today, you really... it is a necessity. ~Um, ~and going back to your point, Fairuz, about this is not Next.js specific,~ um, you know, ~we hopped into the conversation 'cause you mentioned ~that ~that's the way you solutioned it. ~Um, ~but the idea of a [00:19:00] proxy that then serves as a middle chunker, if you wanna call it that,~ and,~ and serves it up to your front end, you could do that anywhere. ~I mean, ~you could do it on a Cloudflare Worker. You could do it,~ like, um, ~on a Supabase function. ~You, ~you... There's a bunch of different places you could do it. In your example,~ um,~ where was Next.js hosted? 'Cause, ~you know, ~where you host it, do you self-host it, it, it depends on how that server interactivity works. Faris: to remember. I wanna say it was AWS or AWS Amplify as a setup. Paul: Got it. Okay Faris: so it was all on the same infrastructure that it was set up. Yeah. ~Uh, ~but ~we also, ~we also... What was very interesting is that because we were a fintech and you have constraints when you have an EMI license, an electronic money license, which essentially means that if you have a certain level of downtime, you have to report it because you may lose your license for being in the flow of funds or so on and so forth. So availability is a big constraint, and so we, with Terraform, actually had a cloud-agnostic setup, [00:20:00] which meant that even if you had a regional failure or you had infrastructure failure of,~ like,~ let's say AWS down, was down entirely for where we needed to support it, you could have the entire thing up on GCP m- super, super quickly. And the way that was set up was making sure that ~you weren't, uh,~ you weren't tied to a cloud provider's n- native solutions that weren't available anywhere else. Like object storage is available everywhere el- ~uh, ~in multiple places, but AWS Am- AWS Amplify is ~sort of ~an orchestrated solution that is harder to maybe tie away from. And so that was also a constraint to think about Paul: And do you think that,~ um,~ the mindset shift here could-- A, a takeaway could be some-something of that form, which is you wanna use object storage. It doesn't have to be object storage. It could be like a Cloudflare worker. But think about the infrastructure component that makes your experience shine, and then what happens if it's only beholden to Next.js, not good. What... ~Or, ~or like Vercel as a hosting provider. Faris: Like [00:21:00] what's your cost? Paul: Yeah, exactly. ~Um, ~so ~what, ~what other types of,~ uh,~ utility do you think that this could provide to especially like that type of persona you mentioned, Faris, which is the front-end oriented developer,~ uh,~ looking to take advantage of augmenting their experiences? 'Cause anybody listening to this is probably going through their head and thinking, "Huh,~ well,~ what big data do I have? ~Hmm, ~I don't have big data, so therefore none of this really applies to me." Faris: I think ~it's, ~it's less so about big data and it's more about asking why. Why did me moving these requests from the client to a proxy change things? Why was TanStack Query an interesting solution here, and what does, what is the cost of taking it away? Or ~what, ~what convenience am I buying by implementing a super easy solution that's natively available to some cloud provider, and what's the cost when things go wrong here? Or maybe I can even flip things where th- some of these [00:22:00] solutions don't necessarily pan out if you flip to another product. Now I don't have these problems at Smallpdf. At Smallpdf there are no bloated APIs that I have to work with because I work with a backend team that I can ask for a brand new endpoint. I literally had a call today. One of our endpoints weren't working. It was like, "Hey, let's just make a new one." Great. We can spin it up in a day, no problem. Nobody else is gonna consume it but us. Where things get interesting at a different level of scale, even if you have lean endpoints, is now what do your resilience patterns look like at scale? Everyone using TanStack Query may just have your global default of three retries. That sounds pretty safe until it isn't, where I've seen actually outages occur as a result of retries. ~So we have... If you've got...~ think we've got easily 50,000 users every 30 minutes. ~Uh, ~so even ~if you, ~if you deploy something and something goes wrong you'll find out pretty quickly. But even separately, it... That is insane. I have, I've never seen something like this. ~Like, um, ~I think there were a thir- [00:23:00] it's a 13-year-old product. I- we don't even use Sentry, we use something called Track:js, and I think even back in the day when ~they, ~they used that, there was the expense of moving over to Sentry because of some ingestion limits or the amount of errors we had to ingest, ~it was, ~it was just unfathomable. Like Paul: That's exactly what I was thinking about is like the volume of the ancillary systems is insane. Yeah Faris: seen days of 120,000 errors in a single day, and it's near impossible to digest that. And so there,~ your,~ your strategic thinking is entirely different, whereas if you're at a startup with,~ like,~ 20 users and each is a high-paying user, great. You can have a customer support call with them or whatever else, and you have a great day. This volume you cannot deal with. So getting to the idea f- back of even lean requests and just plug and play with TanStack Query and you're having a great time or whatever has retry mechanisms. Now, the system we were using for creating subscriptions on our platform called Recurly, that has a rate limit tied to it, and whether it's 150 requests per minute or so on and so forth, there's any issue that occurs at any point in [00:24:00] time where the back end is hitting the upstream provider of Recurly and calling it multiple times or whatever your subscription platform is, whether it's, could be Stripe or something else, any API, and then you have multiple clients initiating retries, or you're in sanctioned countries or flaky network requests, and you're still hitting and not aborting requests or a bunch of things that could be going wrong. What we had is a scenario of one request just about overflowing ~the retry, the, the, ~the API limit, and that means all other API requests failed for a five-minute period. So your ability, somebody modifying a subscription doing something else hit the limit, which meant that people couldn't even create subscriptions because it wasn't a quota that existed per endpoint. It's a quota that existed for an entire provider, entire user. So you can get to a place where you can plug and play all the resilience patterns you want to, but then either you're exhausting your quotas, you're not doing caching correctly, 'cause you [00:25:00] should be doing almost s- very selective caching, not singular rules per data type, knowing what's offline, what's happy, what you're happy with in memory, and then there's costs associated with it, especially in a world where you have u- usage-based billing, which is becoming more and more popular with tokens that we're consuming, versus standard API costs. Your usage billing could just shoot up just as a result of you inefficiently doing retries. And so we had to introduce the concept of what is a retryable error? What is a failure that we define you should be a- you should be allowed to retry? And naturally, a 400 error, a validation error, something being a bad res- ~you know, ~a bad request, you should never retry something like that. But it's also a non-200 request, so a blanket rule would naturally, ~you know, ~re- re-request or do a retry without thinking twice, because we set these rules up very simply. Paul: ~Right. ~Yeah. And ~I mean, ~I've seen that firsthand too, especially using serverless products like the [00:26:00] serverless Redises of the world that y- you can quickly rack up ~a, a, ~a huge bill because you were working with Claude or something and said, "Hey, this is slow," or like whatever, "Throw Redis caching." ~Like, ~please don't do that. It's not... You have to cache with purpose and deliberately, or you're gonna run into those types of issues. Yeah. Faris: this also all over the place with vibe-coded apps these days too, where like infrastructure bills are going through the roof because just hammer the database as much as you want, and you'll get the end result, but it's gonna be costly. Paul: ~Uh, ~so Faris,~ uh,~ where do you think people should look if they want to,~ like,~ explore these thoughts,~ like,~ with a bit more depth? Because there's a lot of content out there right now, and I'm one who loves to also talk about AI tooling, right? But this is something that was refreshing to talk about. It's really about architectures and systems and how we build. So where are you going right now to find more content and inspiration,~ uh,~ to explore these thoughts? Faris: ~I'm, ~I'm [00:27:00] very lucky to be so deeply ingrained in the conferencing circuit where,~ like,~ I get to see and learn firsthand, and maybe even see outages on the day that I'm talking at a conference , right? And so ~there's, ~there's no better way to learn than from failure. I love postmortems. I actually, I love reading postmortems 'cause I'm like, "You reached either a limit of a system or a limit as a result of your ways of working." 'Cause something is either a cultural or engineering setup problem, or something actually is a technical problem, right? And so learning through ~how other, ~how other human beings collaborate, they see and look at problems is ~really, ~really useful, and that's what I, that's what I love about going to conferences. It's nev- I've seldom learnt a lot,~ um,~ just watching a 20-minute talk because generally it's a 20, 30 minute short talk. You get a snippet of an idea of the questions you may wanna ask, and then the hallway track where you're sitting either at the speakers' dinner, you're sitting,~ like,~ afterwards in a talk and you're, like, [00:28:00] knee-deep asking what's,~ like,~ going on with the internals of somebody who's maintaining a library. ~Like, ~I delivered this exact talk in front of Dominik Dorfmeister at hi- ~uh, ~in Vienna earlier this year. And so I was... First of all, I was like, "Okay, who... I'm delivering a TanStack Query talk in front of the guy that maintains TanStack Query." That's an interesting experience first of all. And on top of that, Aurora was also there, and it was a Next.js talk. So ~I, ~I f- I firstly felt misplaced . And then secondly What an incredible place to be where I have the experts in the technologies that I'm trying to talk about, and they have s- they had such wonderful feedback. And then Dominic and Aurora were like, "Hey, you talk a lot about pages router, and you talk about at some point in an optimal way,~ uh,~ in an optimal scenario, if you wanted to do server side rendering for this request, instead of doing CSR, what you could do is make the request to the proxy and it gets server side props." But an, a limit you introduce [00:29:00] there is that if you're making a blocking request on the server, you're not rendering any initial HTML, and then you have that loading indicator in a browser, and there's nothing being sent to the client. So there's nothing interactive, no loading states, nothing like that. And so I was representing that as a problem and an excuse to introduce a retr- a, a timeout mechanism as a resilience pattern. And they were like, "Wait, with Next.js 13 or with partial pre-rendering or with streaming and suspense boundaries, you can actually s- take, start the request on the server, and you could stream that over to the client." And now I naturally could have also maybe read this somewhere online, but ~like... ~And you don't have an exa- you don't have a case every single day where you've got TK, Doto, and Aurora to be able to bash out the problem yourself and figure out the solution. But there's so many resources on Blue Sky, on Twitter, and there are incredible people sharing their knowledge, looking how people are solving problems in open source. You have the,~ uh,~ npmx, which was an incredible project and a feat of performance work to improve how we, ~you know, ~go through the npm [00:30:00] package registry. There's a lot to learn there and a very welcoming community. ~Um, ~and I think it's very refreshing in a world where I've started to struggle a little bit more reading online content just because there's a lot of slop out there and a lot of regurgitated articles in the form of something that's been AI written ~and, ~and you get also a lot of exhaustion or overwhelming. ~Uh, it, ~it gets very overwhelming seeing everything in a written,~ uh,~ fashion, and you're almost getting review fatigue, right? I'm reviewing what my LLM is showing me, my reviews. Things are getting meta where Claude writes the code, Claude reviews the code, and I read. It's a lot. So being conversational, intentional, following the right projects and the right people will take you really far, and being open to engage in the right conversations and developing interpersonal skills will take you far further than going and just me suggesting a particular blog website. Paul: ~Well, ~cheers to the new internet, the meta Faris: Yeah. Paul: Yeah. And if people wanted to find more about you, Faros, I know you [00:31:00] mentioned your site earlier, could you just remind listeners where to go? Faris: Yeah. ~Uh, ~luckily,~ uh,~ my name is SEO friendly, so Faris Aziz, you pop it into Google, there's a website called Faziz, F-A-Z-I-Z, dash dev.com. ~Um, ~I recently did purchase farisaziz.com, so I do need to make that switch. ~Um, ~yeah, and,~ uh,~ you can find out a lot more information, but I'm also super active on LinkedIn, Blue Sky, so happy to also have people reach out to me and me send them links. But ~all, ~all my talks are up on my website, and I also version them almost like a Git history in a sense, so you can actually see the evolution of talks and improvements along the way, and which one had higher success at different conferences to be able to understand,~ like, you know, ~what were the different phases of its evolution Paul: Yeah,~ that's,~ that's really cool. I'm sure there's a lot of,~ uh,~ presenters that would appreciate something like that to help to- ~uh, ~tune their own. ~Well, ~and anyway, thank you so much for coming on. It's been a pleasure, and hopefully we can have you on again soon to talk about more,~ uh,~ actual engineering and [00:32:00] architecture Faris: Yeah, with pleasure. Thank you