Sometimes, you're enthusiastic about simplifying a process but just becoming world-class in a particular domain allows you to claim a space in the market in people's minds.
Check out our open-source Feature Flagging system – Flagsmith on Github! I’d appreciate your feedback ❤️
I'm super excited to chat with Guillermo Rauch. He is the Founder and CEO of Vercel and the originator of a bunch of stuff but most successfully, the Next.js framework, which looking at GitHub is closing in on 100,000 stars.
That's wild. You're breaking the news to me. It's incredible.
Every time I look, it's a new big number. It's pretty wild. We also passed 200 million downloads and everything seems to be happening so fast. It's fascinating.
He was right because, at the time, he would've loved to have found React components, the type script ecosystem. The kinds of frameworks that we're building with things like Next.js. The infrastructure automation that comes with that when you deployed Vercel or other providers. All of that didn't exist at the time.
Tell me a little bit about which came first. Was it Zeet? I never was quite sure but which came first? For the record, I always preferred the first name but I understand these organizations in Germany that had it.
A lot of people that were with us at the time loved the name. The question of what came first, the chicken or the egg. Where I hear a lot is like, what came first, the idea of deploying very quickly or the idea of creating a framework or what came first, the idea of simplifying global delivery or the idea of a framework? The key thing that has made us successful, which is what I always encourage is open-source enthusiasm. To think about is, what about both? What about the conception of a system where it gets better when you think about the cloud counterpart?
In our case, it gets more global. It gets more resilient. It gets more dynamic. The operations go away. At the time, I was obsessed with the two problems. It's too hard to start an app. It's too hard to assemble your framework, which is essentially what you had to do back in the day. At the same time, I was like, “It's too hard to also provide the infrastructure. It's too hard to deploy. It's too hard to do zero downtime deploys.” Believe it or not, that was my very first experience. I remember vividly, that I was messing with Webpack and Kubernetes rollout strategies for front ends. I was like, “There's got to be something better than this.” The two things co-evolved but they're better because of one another.
You didn't answer the question. Conceptually, was it like, “I'm going to build a framework that expresses itself best when you are deploying it onto infrastructure that we control?” That, to me, is the huge amount of value that you get when you're deploying the next project on Vercel. I want to talk a little bit about that.
It came from a DX point of view. The two emerged concurrently. If I have to place them on a linear timeline, I would say the idea of getting something up in the cloud and being able to share a hyperlink and collaborate instantly with people. That came first but what is that something that you're sharing? Very quickly, I realized that what I wanted to share was sites, apps, web projects, and front ends.
That allowed us to zero in on what it is that you're deploying. That's another thing that has been a key finding, I would say, which is that sometimes you're enthusiastic about simplifying a process. Becoming world-class in a particular domain allows you to claim a space in the market, in people's minds, so where Next.js has helped a lot was that, “We're going to be able to deploy front-end projects very quickly and we're going to be excellent at that.”
We're going to say, “Bring your data from other places. Bring your configuration from Flagsmith. Bring your CMS data from Sanity or Prismic or the CMS of choice for your project. Bring your data from Firebase, PlanetScale, or Neon.” We started realizing, “What are the integration possibilities that follow?” It all started with DX. We zeroed in on what we were best in the world at then we started integrating with other folks to make this thing a true platform.
The early days of Next, can you describe the version nor 0.1? It was a React-based like site generator in the very early days?
Not a lot of folks know the story of what I called N4. N4 was a typo. What I wanted to do is have a code name for Next before releasing Next. It was supposed to be N3. Meaning N and the three letters but I accidentally code that N4. The true inspiration for Next, in the beginning, was PHB because it was this idea of you writing a file. That file automatically becomes your route and everything is extremely ergonomic.
Let's get right into the problem. Fundamentally, if you zoom out what we're doing on the web is stringing together, piecing together HTML over the wire. Especially because our focus at the time was very heavily on being a server rendering layer on top of React and the Next inspiration was PHB. The thing that also PHB had was this ergonomic syntax for how to embed logic into this template of HTML. PHB has a lot of surprising features in that simplistic design. It can stream the HTML by default. It's serverless in that each request claims its own arena.
A lot of people don't know that. I only discovered that when we were writing our SDK, then it was like, “How do we write half the SDK?”
How do you start doing share state and whatnot? Starting from constraints is a good thing. A lot of people that end up solving that problem with PHB end up having a quite resilient serverless system of sorts. Most people are deploying PHB inside servers. I've seen that a vape per project where folks deployed or there are a bunch of projects now for turning PHBs quite trivially into serverless functions.
There's even an extension of our cell that makes you do that. The inspiration was there like, “This is an easy thing.” PHB got a lot of folks started with development then it's scalable. It powered Box, Yahoo, Facebook and it was a good blueprint for scalability as well. That's what I wanted in Next.js. Initially, it was to solve our own pains. It all started with Vercel or Zeet at the time needed an ergonomic way of putting out content. We want to put out our landing page. We want to put out our blog to start writing up our console.
This is another interesting property. We had the ambition that the system is so dynamic in versatile that it can express any webpage. Whether it's Flagsmith.com and you're telling people to sign up, log in, and marketing content or I'm logging in and managing my configuration and my flags. We thought this was possible because React as the engine models the world as components. The framework can be smart enough to say, “This part of the system, we statically optimize. In this part of the system, we do dynamic server-side rendering with streaming or this part of the system, we combine both.” It's also provided us with our scalability, which is that we've been so versatile with ultimately what customers want and need.
In terms of the things that you've focused on with Next, has the developer experience always been the number one thing that you've cared about over everything else?
I remember thinking, “We're not going to be able to compete with native mobile apps with that approach because the web works in this way. Every time you go to a site, you're downloading the entire app. Whereas with mobile native applications, you pay the cost of the big download once.” They have an interesting point in the trade of space because people are somewhat okay with downloading 200-megabyte apps, 100-megabyte apps, and 50-megabyte apps because they do it once.
With the web, we don't have that model of installation, which is a great thing. It's a great evolutionary pressure but the web was trending towards a mini version of that. Now download this 2-megabyte bundle, and 5-megabyte bundle to render a page. It was DX but it was DX in the service of a great end-user performance dream.
That's why it made us successful too, is that we said it's DX for server-side rendering. It's DX for per-route code splitting and all those things. Looking back, it would've been bad for us if we had only focused on DX. When I talked to other dental makers or founders, you have to be aware of that. The problem is that markets can reward DX in the short term because you're going to get lots of love. Someone will pick up your tool during the weekend and be like, “This has changed my life for my side project or whatnot.” The big challenge is whether you can get that reaction and also solve hard enterprise problems.
As the developer, you don't know about that. It just works. As the user, things are as fast as they can be and things are hydrating. You are only updating components. Quite often, frameworks have this one big caveat. We've to punt it on X because that's super hard or we can't do it. There's some of the stuff like the service side rendering, which you wouldn't be able to do if you were running out of S3 or something.
What you're getting at is something that's dear to my heart. I fundamentally believe that on the web we can have the cake and eat it, too. You can make it easy. You can make it lightweight to do the initial load and you can make it extremely interactive on the client side. An initial inspiration for Next.js that I haven't talked about much about was how GitHub would server render their issues their rate means. They are like all these critical parts of the system that has set a non-negligible advantage for their business. First, the SEO benefit like the amount of traffic that comes into GitHub through Google searches is tremendous.
Also, the shareability aspect. I can link you to my PR. I can link you to my issue. I can link you to my newly pushed commit and to you, they have some performance challenges to work through especially as they've grown but within seconds, usually a second. Now you get all the content that you were interested in without that expensive install/bootstrap/download/spitter face. This is the cake and it too part. For example, the checks will update in real-time.
New comments will come in. New reactions to your comments will come in, so you're picking up from where the server left off and you're updating the UI in real time. This is what I think is the fundamental advantage of the web that over long periods of time will make it win over every other platform because you're having that shareability, virality, and instant initial load without pre-existing state on the client device. Plus, now the UI is super interactive in real-time.
There are a few systems that have accomplished this. This is the fundamental thing that React did for the world. They gave us a model for how we could do server rendering and we can also do reactivity on the client side. What we're working on now is what you mentioned around, “Can we hydrate selectively? Can we stream and only make or prioritize the download of JS and CSS to the parts that are on the screen?”
That continues down this evolutionary road of making things even faster and more streamlined. Sometimes, I've given folks a metaphor of Netflix has this awesome technology for streaming video that is adaptive to your connection quality. One day they said, “We're going to put out this ability on the client or on your TV, interact with the content.” They did this interactive story for Black Mirror that they called band or snatch.
That's what I think. If you extrapolate it and you said, “All content is like this.” This is what I think the ideal instead of the web is where a server is adaptively and selectively streaming in the most optimal way possible for the client. That client might be a low-end mobile device where we stream the required CSS for the responsive view.
I don't need to stream in parts of the run time to deal with models or views that are not necessary for that experience. On the client, I'm immediately commenting, reacting, collaborating, and getting up real-time updates. Again, very few folks have gotten to this point where this is the average web experience but by investing in frameworks and infrastructure, we can democratize access to this thing.
I remember my friend who runs DebugBear. They have an integration with you folks. He did a performance comparison between Google Cloud.
I love their blog post.
He realized that Google Cloud had a spinner for a spinner. At that point, you're like, “How did we get here?” A lot of what you've talked about does require a server run time like classically front-end frameworks and front-end hosting platforms and things of that nature, didn't provide. Was that always in your head of, “We're going to need some service side compute resource?” When you were designing Next, was it like, “We are designing it with that to exist at some point in the future?”
That's super insightful. The other aspect of having the deployment platform to your point is that if you want to make this vision come true, you have to democratize access to server compute. You have to democratize access now to edge compute and you have to lower the cost. One of the awesome things that we're working on now is that we're moving a lot of this work that happens on the server to this modern, what we call the edge run time.
This is a run time that uses only web APIs and makes them work on the server side. This edge run time is standard-based and is compatible with CloudFlare, Dino and all of the modern server-side run times. One of the key awesome things about this edge function primitive that we're introducing is that as serverless did in the past, we're lowering the cost and we're increasing the performance of server-side computation.
Lambda have had this issue. They have a cold start. They don't do well with workloads that are doing or waiting a lot on IO, which is a lot of what we do with rendering. It's querying a database waiting. Whereas, with systems like Lambda, you're like, “I'm paying for this one CPU core to be stalled on waiting on IO,” then concurrency goes up and like all of these things. That was an incredible tool at the time when we introduce our first version of our server’s infrastructure for democratizing that access to server-side rendering.
Now we're doing it again and we're lowering the cost by another important factor. With edge functions, a lot of those issues like cold boots or concurrency or waiting on IO are not as problematic anymore. Without having access to that cloud infra, it would be hard to popularize a framework like Next.js. However, we learned along the way that compute can take many places.
One of the interesting things about the static side generation capabilities of Next.js is that you can say, “I want to do some of the compute at build time before release.” I very much think about the world in the old compiler metaphors of ahead of time, AOT, and just in time. You think when you give the customer the option to say, “Do you want to do some work or all of the work ahead of time?” You can get rid of that server-side dependency to a great degree for very simple things usually but I'm glad that we have that capability to say, “I want to opt out of having a server.”
Sometimes there are good reasons for this. I'll give you an example. Some folks use Next.js to power electron apps. They want the app to boot up from static bundles and static HTML pre-rendered pages that have been deployed directly to the device, that have been downloaded. I like that with Next.js, we can express that versatility.
It's not that you always need a server or an edge to be able to render but over the next few years, what we're going to see is that a lot of workloads are going to move there because it aligns the incentives of the consumer and the business well. As a business, especially if I'm eCommerce, I'd rather spend a little bit more on server-side rendering and make you more increase your propensity to buy.
Sometimes I give folks a physical, real-world analogy of, “Imagine if Walmart put a lot of obstacles for you to get into the store. Imagine if they made you sign a waiver for your GDPR cookies and gave you four doors that you have to open that represent spinners. Imagine all that additional latency and what that would do to the revenue.” That's what's happening on the web now.
For people who are not too aware of the Vercel platform, a few years ago you announced cloud functions but they would only exist in one place in the world. People use that stuff for things like authentication.
Service rendering, yes.
You introduced a new feature of edge functions and just so I understand it. Are they like the same run time that was existing in one place in the world globally or do they have different properties?
They have slightly different properties. Let's start with the beginning. You write your Next.js app. You’re doing a service at rendering, doing off to your point then you deploy it. The old way of deploying is you deploy to a server in one place in the world. You have to deal with scalability, multi-AZ deployment, zero downtime rollouts, caching, and all of those properties. In the Vercel world, we said, “It has to be serverless. It shouldn't require ops for the most part. Availability has to be solved for the customer redundancy, resilience, etc.”
We use this primitive that we introduce as a product called serverless functions. We democratized access to serverless and to compute in the cloud by making it so easy that your next phase project is converting automatically into this infrastructure primitive that scale well. To your point, there were some challenges with this technology. One of them was a cold wood problem. When you access a page, you could be waiting on the instantiation of that unit of compute.
We solve that problem to a large extent because Vercel itself is an edge network. What we can do that's cool is we can create pages, cache them, and distribute them worldwide on your behalf. We call that technology ISR. This moved the Jamstack world, introduced a quantum leap to Jamstack because now instead of having to rebuild your entire site to get these cool properties of CDN cashing and whatnot, you can now make changes to your pages at runtime and get the same benefits. I can have my CMS say, “We changed this.” A serverless function is invoked usually asynchronously. The user doesn't even see that cold boot.
We produce a page. We distribute worldwide. It's done wonders for eCommerce, Web3, and other places that receive a tremendous amount of traffic. They don't want denial of wallet attacks. They don't want their compute build to skyrocket. They also don't want slowness on the user side. They don't want to overwhelm their backend. This technology, by automating this caching problem, reduces your backend build tremendously.
As the world wants to become more dynamic, these caching tricks are not enough. What we sought was a run time and an infrastructure primitive that could do dynamic service side rendering globally without cold boots with the ability to stream. None of these trade-offs that service compute put forward. What we introduce is this concept of the edge function. The run time is slightly different. You can't run all of Node.js.
You can run a subset but what we're doing is that it has deep framework integration. In Next.js, as you start operating, we're going to start defaulting to the edge run time. This is going to make your application automatically compatible with this new form of compute that's much faster, much more cost-efficient, and global in nature.
Interesting. You've got a bunch of node modules that you're prepackaging with these edge functions. I can't say, “I want to use some random package.”
This is going to be a distinctive capability of Next.js, which is that Next.js is multi-run time and it can be multi-run time on a per-page basis. In the beginning, a lot of folks will benefit from having the choice but over time, I expect the entire world to run on top of this more modern API run because there are so many benefits. There's also the benefit that when Node.js first came out, the web didn't have all the APIs necessary for expressing server-side code.
We didn't have a module system, so Node.js has to invent one. We didn't have a way of fetching data. We didn't have the fetch API. Next.js I started to invent the HTB module. Now the web, especially due to the introduction of service workers and things like that, has a lot of these APIs. There's a request global, a response global, and a fetch global. There's a strong case. We're saying, “Let's have the same web everywhere. The same way web API surface everywhere.” There's going to be a smooth transition, especially if you use Next.js from the old serverless world to this more modern faster edge world.
The one thing that's we haven't talked about yet is databases and the difficulty is around the state, especially when you trying to do things globally. You folks have achieved a lot. I don't think emission is the fair word but the fact that you haven't tried to take on that problem directly either through the next platform or through Vercel. Are you saying you can go and use MongoDB Atlas or DynamoDB or whatever data or is that something that you want to want to work on? It's not a small problem, right?
If you allow me to nerd out, there are two ways of looking at the state on Vercel. One is a simplistic one, which is, “Vercel is stateless.” It runs compute. However, that wouldn't be accurate. You can also argue, “Vercel is this globally distributed key-value store optimized for the delivery and compute of pages on the web.” If I go and look at my infrastructure, I'll use an example of ISR.
ISR allows you to say in Next.js, “Get this data.” We purposefully deploy that function next to your database because we know that there could be waterfalls of the data. You might want to go back and forth and make five queries to generate a page. Once we grab the data, we now have this artifact that can be globally distributed and invalidated when the data changes.
We're materializing like in the world of databases, it is going to be considered a materialization or a view function of sorts. When I access the patient in Tokyo, even though the data fetching happened in Virginia, in Tokyo, every single page will be fast and resilient because, for a lot of these workloads, we can apply stale if error semantics.
Even if you made a change and the regeneration of the page failed, you're online in Tokyo, which is incredibly valuable. There are all these APIs that we've built and all these primitives of our infrastructure that deal with, “How can we solve the problem particularly of accelerating web delivery?” What our roadmap looks like now is exposing a lot of these primitives to the customer and to framework vendors to create even more powerful dynamic experiences.
I'll use an example with Flagsmith. Maybe you have a deployment of Flagsmith on-prem, VPC in Ohio, USC too. That's where your source of truth of configuration and features live. Now you have Vercel. Vercel is saying, “To make things fast, we need to personalize at the edge. We need to render at the edge. We need to deploy your front and globally.” How can you marry these two worlds?
Vercel introduce a primitive called middleware. Let's say that my page uses traditional server-side rendering or is static. According to a feature flag, I want to provide two variants of a page to the customer. Now we say, “You have this capability called edge middleware.” Now you can run JS every time you get a request to a page in Tokyo, in Ohio, or in Buenos Aires but the problem remains.
“Now I have middleware, that's awesome but my feature flag storage is in Ohio. How do we bridge that gap?” Vercel will give you the ability to materialize your configuration changes onto our network. Now every time middleware runs, it will have a copy of a subset or all of the feature flags and configurations that you've done in Flagsmith. Now that's available and we guarantee its performance and availability in every edge of the world.
I can say in Tokyo confidently, “If dark mode, if designed 2.0, if chat,” using the examples from your homepage. I can now start directing traffic. I can start making high-level routing positions. I can use the same technology to decide, for example, geofencing. I can say, “We're not currently servicing this location or this country because of regulatory reasons.” That's the first version of this.
The next version is that we'll continue to do more of their rendering at the edge. The strategy there will be to delegate parts of the rendering to compute in the places where the data lifts. The reality is that we can't magically make all of the data global. For some customers that would be prohibitively expensive. To answer the other part of your question, when you have to say, “For this part of the page, there's no caching story. There's no edge story.” We'll stream from the origin of the data. In that case, you can use Mongo, PlanetScale, or whatever.
A lot of this databases are also starting to introduce a global story themselves but it's not going to be in twenty locations. It's going to be like in 3 or 4. For my customers in Europe, the customer access through London. I can execute some routing logic there. I can make some early compute decisions but if not, I delegate to Frankfurt. Frankfurt is where my primary database for Europe lives and will continue to do some compute there.
I feel like the industry's dragging itself toward that point. We built an edge API similar to what you described but there are a couple of features that we have that meant that we needed per-user data, which meant replicating that data. It does feel like we're dragging ourselves there but there are a lot of sharp edges around the tools for those sorts of things now. It's interesting as well. You look at CloudFlare. I love their platform. It’s like they're wrestling with these ideas of state.
They've got these durable objects which are weird and interesting and have some interesting properties. They have this heavy store that's completely different. You can't get around the problem. You can't work around the CAP Theorem Problem. Eventually at some point, especially, if you want this transactional integrity, there has to be a compromise. There has to be probably a performance compromise.
There are trade-offs. One of the things that we can do with Next.js for that performance cover on my side of things is this. One simple model is are you okay with having a slightly stale copy of the data at the edge? This is the case for eCommerce. Are you okay when you first server under the page it says a stock one? Even while you were server rendering, the stock has already changed. Arguably, the whole world is in this rolling motion of changes.
That's why I spent time talking about how it's important for the client you stay plugged into subsequent updates that you happen to the data and how React and Next.js are pioneering models to solve this problem. There are cases sometimes where you don't want to replicate data at all. You don't want to cache data at all. Where we can help there is that we can do an initial flush at the edge. The edge is very relevant even in that world because we can do an initial flush of the structure of the page. There's a detail that's super important, which is that we can also start streaming resources that we know you will need even though the data is not here yet.
This is an interesting thing that perhaps sometimes is misconceived. You say, “I don't have an edge story because my data only lives in US East and I don't cache.” Everything is user personalized. Even then, the edge can start again, facilitating the streaming of resources and giving a faster initial paint to the customer. To your point, even when data trade-offs exist because of not only the CAP Theorem but also the speed of light and all these things. The framework will help the customer provide the optimal experience for those constraints that you have with your data.
It's interesting as well how almost everything that you've talked about relies on everything being component-based. If things weren't component-based, you wouldn't be able to do any of this stuff or you would but it would be hard.
It'd be hard. I'll give you an example of where compos are so awesome here. You can toggle that property in a component and say, “Render as a skeleton.” You can reuse all that code, all the layout structure, all the nested but you can say, “I'm rendering in this state the skeleton way.” Now, going back to that idea of like I'm in Tokyo, I arrive at the page. The data's not there. I flush the version of the components that will be populated eventually with data then I delegate the streaming to my origin in US is to one. To your point, doing this with templates would be this nightmare of copy-pasting and lack of reusability.
You wouldn't bother. Did you realize how important it was as a design choice when you took it?
I had a lot of instincts because I was the creator of a framework called Socket.IO for real-time communication. I had this nagging feeling that I was focusing too much on transport technology to solve the problem of real-time apps. When React came out, I had this weird realization or instinct of, “This is the solution to my problem.” Even though they're completely different technologies, it's like, how can you compare a web socket event thing with a framework for components?
It has to do with that idea of components help you model the problem better. They make the transport mechanism redundant in a way. It doesn't matter whether you're streaming, static side generating, server-side rendering, or pulling versus pushing. It's this technology that's allowing you to repaint over time and paint different variants of things over time. I had an instinct. I can't like give myself credit but I do give myself credit. When I had this realization, I dropped everything. A little-known fact, my initial startup was going to be around doing something more with the ideas of Socket.IO and it pivoted hard to doing things with components. I had the instinct at least.
What's next for Next? What's next for Vercel? I love what you said, “We're building a database product,” but I'm not expecting you to say that.
We're building these interesting data APIs that will allow you to make better use of the edge, for sure. We're moving the world forward into this faster, cheaper, better way of server rendering at the edge. We're adding more compatibility. We're trying to bring the entire ecosystem along this journey. We're introducing an API called the Build Output API. All this technology that I mentioned, all this automation where we run the build process of Next.js and we convert it into this awesome infrastructure, we're exposing that as an API for every framework in the world to use.
Breaking news because it's not out as of the recording of this episode but it's already integrated with Next three Veet plugging SSR, Astro. It's amazing because it's exposing all the guts and not every customer in the world will benefit from this directly because it's like that internal API. Now any framework author or advanced user can now have full control over the infrastructure. That's coming out soon. There are a lot of awesome improvements to Next.js. Not the core rendering itself, which of course is getting so much better with streaming and React components and that progressive hydration that we talked about.
Also, things like the image component where we're giving you optimal images with a lot better DX. We're trying to improve all the other CO2 emissions of the web where a page is not just as slow because you didn't have server-side rendering. Maybe you had lots of client-side scripts that were also impacting its performance. Next is also helping you automate and make sure that those perform well.
That's awesome to hear. Guill, it's been great chatting with you. I can't wait to see what comes next. I'm not sure how long it will take before you folks get to a hundred thousand but maybe we could have a catch-up when that happens and see where we're at.
We will. Deal. Thanks so much,.
Take care man.