<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pablo Bermejo</title>
    <description>The latest articles on DEV Community by Pablo Bermejo (@peibolsang).</description>
    <link>https://dev.to/peibolsang</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F77947%2Fbf375741-6135-4427-b36a-2a67166560e2.jpg</url>
      <title>DEV Community: Pablo Bermejo</title>
      <link>https://dev.to/peibolsang</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peibolsang"/>
    <language>en</language>
    <item>
      <title>Experimenting with every Next.js 14 rendering option: From SSG to Partial Pre-rendering</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Mon, 22 Jan 2024 10:51:50 +0000</pubDate>
      <link>https://dev.to/peibolsang/experimenting-with-every-nextjs-14-rendering-option-from-ssg-to-partial-pre-rendering-2il1</link>
      <guid>https://dev.to/peibolsang/experimenting-with-every-nextjs-14-rendering-option-from-ssg-to-partial-pre-rendering-2il1</guid>
      <description>&lt;h1&gt;
  
  
  Why am I doing this?
&lt;/h1&gt;

&lt;p&gt;Early this year, &lt;a href="https://x.com/peibolsang/status/1742867155043946809?s=20" rel="noopener noreferrer"&gt;I migrated Octotype&lt;/a&gt; (a blogging platform I created using GitHub Issues as a headless CMS) to Next.js 14. The migration experience itself was great, and working with the new App Router and React Server Components was bliss. The mental model these two new paradigms bring to the table is absolutely a step in the good direction for a better DX (and, therefore, for a better UX).&lt;/p&gt;

&lt;p&gt;Because Octotype does not have a database and relies fully on a 3rd-party API (GitHub API), I got obsessed with fine-tuning the site's performance to the maximum. Little did I know that I got drunk with options, and &lt;a href="https://x.com/peibolsang/status/1743024317368012934?s=20" rel="noopener noreferrer"&gt;I struggled to understand the differences&lt;/a&gt; between all of them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Static Site Generation (SSG)&lt;/li&gt;
&lt;li&gt;Incremental Site Regeneration (ISR)&lt;/li&gt;
&lt;li&gt;Traditional Server-side Rendering (SSR)&lt;/li&gt;
&lt;li&gt;Streaming&lt;/li&gt;
&lt;li&gt;Partial Pre-rendering (PPR)&lt;/li&gt;
&lt;li&gt;Bonus: Single Page Application (SPA)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After a few days, &lt;a href="https://x.com/peibolsang/status/1748746537788694560?s=20" rel="noopener noreferrer"&gt;I finally figured it all out&lt;/a&gt; (or that's what I think 😇), so here I am sharing what I have learned. This is a summary of all the rendering options brought to the table by Next.js 14, and during this post, I'll direct the tradeoffs of each one of them with real code examples and videos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: All the examples revolve around loading a user page that contains all their blog posts. The page renders a header with the user name and uses a React Server Component to fetch and render the user's posts. I have mocked a slow 3G connection in all the videos to make conclusions more evident. Also, I used Vercel to deploy my site.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's get into it!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. SSG
&lt;/h2&gt;

&lt;p&gt;One of the first lessons I learned is that Next.js pre-renders your site entirely at build time by default. This means that even if you use React Server Components, the server &lt;em&gt;is&lt;/em&gt; the CI server. It will both fetch data and render HTML on the server at build time, so the browser will just need to download static files (HTML, CSS, and Javascript).&lt;/p&gt;

&lt;p&gt;This is what we call Static Site Generation because now your entire site is static.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I &lt;em&gt;believe&lt;/em&gt; that even if Next.js would still create static output, it would also generate a Node.js server that serves that static output. This is why, by default, SSG mode in Next.js emits a Node.js app. Or that's what &lt;a href="https://gist.github.com/gaearon/9d6b8eddc7f5e647a054d7b333434ef6#deploying" rel="noopener noreferrer"&gt;Dan says&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are some examples. This is how my user page looks like with SSG. Nothing is magical here; it's just a normal Next.js page using a &lt;code&gt;UserPosts&lt;/code&gt; RSC.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app/[user]/page.tsx&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/server/user-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserPosts&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is what my &lt;code&gt;UserPosts&lt;/code&gt; RSC looks like with SSG. All it does is call a &lt;code&gt;getUserPosts()&lt;/code&gt; function to fetch posts (yes, usingNext.js augmented &lt;code&gt;fetch()&lt;/code&gt;) and pass the data down to a &lt;code&gt;UserPostsGrid&lt;/code&gt; client component for final rendering.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;components/server/user-posts.tsx&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserPostsGrid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/client/user-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUserPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/lib/api.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserPostsGrid&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;UserPosts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see in the video, the navigation is pretty fast.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/peibolsang/octotype/assets/3844521/db080d97-7750-431d-8482-5bff407d4525" rel="noopener noreferrer"&gt;SSG Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this is why it's fast. At run time (&lt;code&gt;time&lt;/code&gt; arrow), all the browser does is download static content because the actual data fetching and rendering has been done at build time. Put in a graph, SSG can be represented like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2Fcb955382-6d28-4d04-bd3e-4bc2de6b854a" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2Fcb955382-6d28-4d04-bd3e-4bc2de6b854a" alt="SSG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PROS&lt;/strong&gt;&lt;br&gt;
✅ Amazing performance with a ver low loading time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONS&lt;/strong&gt;&lt;br&gt;
❌ I don't have dynamic data! If the user writes a new blog post, I need to build the site (manually or force a build) so it can be included in the static output&lt;/p&gt;

&lt;p&gt;It would be nice if I could configure my app to automatically build the site every &lt;code&gt;x&lt;/code&gt; seconds to guarantee fresh data at a given time.&lt;/p&gt;

&lt;p&gt;Well, enter Incremental Site Regeneration.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. ISR
&lt;/h2&gt;

&lt;p&gt;Incremental Site Regeneration allows you to configure your site to generate a static output automatically at a given configurable frequency.&lt;/p&gt;

&lt;p&gt;And this is where I started to get drunk with options. The thing is, Next.js is super-flexible and allows you to define what is &lt;em&gt;that&lt;/em&gt; static output. In other words, you can configure your revalidation frequency at the page, component, or the &lt;code&gt;fetch&lt;/code&gt; request levels. &lt;/p&gt;

&lt;p&gt;Because I am a big fan of React's component-driven model, I started putting it at the component level. I leveraged the new Next.js 14 &lt;code&gt;cache()&lt;/code&gt; function available in the &lt;code&gt;next/cache&lt;/code&gt; package. It's unstable, but my site is simple, and I have yet to find any problems. This implementation basically follows a &lt;code&gt;stale-while-revalidate&lt;/code&gt; pattern, where you specify your data fetching function, tag your cache, and establish your revalidation frequency. I love this pattern because it serves you stale data for a period until it's time to serve fresh new data, &lt;a href="https://nextjs.org/docs/app/building-your-application/caching#time-based-revalidation" rel="noopener noreferrer"&gt;which has been fetched in the background by the Next.js server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is what my &lt;code&gt;UserPosts&lt;/code&gt; RSC looks like with an ISR of 1 hour. No changes are needed to my user &lt;code&gt;page.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;components/server/user-posts.tsx&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserPostsGrid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/client/user-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUserPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/lib/api.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;unstable_cache&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;revalidateUserPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;unstable_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;revalidateUserPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserPostsGrid&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;UserPosts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;PROS&lt;/strong&gt;&lt;br&gt;
✅ Amazing performance for cache hits&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MEHS&lt;/strong&gt;&lt;br&gt;
🔶 Eventual fresh data&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONS&lt;/strong&gt;&lt;br&gt;
❌ Mediocre performance for cache misses&lt;br&gt;
❌ Data is not fresh on demand&lt;/p&gt;

&lt;p&gt;ISR is great for many use cases, and I actually use it in other parts of &lt;a href="https://octotype.app" rel="noopener noreferrer"&gt;Octotype&lt;/a&gt;. However, if you (like me) are unwilling to pay the costs of these tradeoffs and always want fresh data at particular parts of the application, you may want to render your content dynamically on demand.&lt;/p&gt;

&lt;p&gt;Now, enter Server-side Rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Traditional SSR
&lt;/h2&gt;

&lt;p&gt;This is equal to the traditional rendering model (PHP, JSP, ASP, etc.), where your data is fetched at the server, and your page is rendered based on that data. The client then downloads a fully operational page and hydrates it so the user can start working with it.&lt;/p&gt;

&lt;p&gt;I won't enter into debates about if Next.js is reinventing these other technologies mentioned above. The main difference for me is the ability to combine server-side rendering with rich client interactivity following a component-based model (not MVC, there are no views here) where your UI is expressed declaratively. That mental model, for me, is a perfect fit.&lt;/p&gt;

&lt;p&gt;Now, this is what my &lt;code&gt;UserPosts&lt;/code&gt; RSC looks like with SSR. No changes are needed to my user &lt;code&gt;page.tsx&lt;/code&gt;. I only had to stop using the &lt;code&gt;cache()&lt;/code&gt; function and start using the new &lt;code&gt;noStore()&lt;/code&gt; function. This forces my component to be completely dynamic and always fetch data on demand. Again, Next.js allows you to define this dynamism at the page, component, or &lt;code&gt;fetch&lt;/code&gt; levels, but you already know my choice and way.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;components/server/user-posts.tsx&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserPostsGrid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/client/user-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUserPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/lib/api.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;unstable_noStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;unstable_noStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserPostsGrid&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;UserPosts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With this change, the navigation to this page isn't that fast. I am always getting fresh data at the expense of loading time. But this comes with a caveat; now, because I am using a &lt;a href="https://nextjs.org/docs/app/building-your-application/caching#time-based-revalidation" rel="noopener noreferrer"&gt;dynamic component&lt;/a&gt; through the &lt;code&gt;noStore()&lt;/code&gt; function, my whole page route becomes dynamic, as you can see in this video:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/peibolsang/octotype/assets/3844521/5d29ca02-9a2e-4290-8687-699081a78ba5" rel="noopener noreferrer"&gt;SSR Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we put this in a graph, this is happening.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2F338d7750-7f9f-42d3-9efb-bbf53d319106" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2F338d7750-7f9f-42d3-9efb-bbf53d319106" alt="SSR"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PROS&lt;/strong&gt;&lt;br&gt;
✅ Always fresh data&lt;br&gt;
✅ Better perceived performance&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONS&lt;/strong&gt;&lt;br&gt;
❌ Performance could be not great for huge data loads or slow data connection links&lt;br&gt;
❌ By using a dynamic component, my whole page route becomes dynamic&lt;/p&gt;

&lt;p&gt;I think people working at Next.js realized these tradeoffs and asked themselves: "&lt;em&gt;Why do data fetching and rendering have to be sequential?&lt;/em&gt;" If you look at the &lt;code&gt;UserPosts&lt;/code&gt; RSC code above, the server first fetches the posts and only then starts rendering the content. It means rendering is blocked by data fetches, but not all that content depends on data! If only there were a way to parallelize some of the things that happen at the server!&lt;/p&gt;

&lt;p&gt;Enter Streaming.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Streaming
&lt;/h2&gt;

&lt;p&gt;Streaming is like chopping up your data into chunks and sending them over progressively from the server to your screen. This way, you're not stuck waiting for everything to load before you can use the page. You get to see and mess around with parts of the site without hanging around for every piece of data to appear.&lt;/p&gt;

&lt;p&gt;I like this approach because, in my mind, a chunk equals a component. This is the mental model I use, so this thing immediately clicked for me. &lt;/p&gt;

&lt;p&gt;In my code, all I had to do to enable streaming when I deployed my site on Vercel was add &lt;code&gt;Suspense&lt;/code&gt; boundaries around my RSC. Practically, this means adding a &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; tag with a fallback, which is a component that will be rendered while my RSC gets processed (i.e., data is fetched and HTML is rendered) in parallel.&lt;/p&gt;

&lt;p&gt;This is all it takes to enable streaming. There are no changes to my RSC, just a tiny change to my &lt;code&gt;page.tsx&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app/[user]/page.tsx&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/server/user-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserPostsSkeleton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/skeleton/user-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserPostsSkeleton&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserPosts&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see in this video, there is an improved real and perceived performance when loading the user posts. The page is shown faster, and a skeleton is rendered while the data is loaded and streamed in parallel. This is because the JSX inside the &lt;code&gt;return&lt;/code&gt; statement is processed parallel to the &lt;code&gt;UserPosts&lt;/code&gt; RSC processing (data fetching and rendering).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/peibolsang/octotype/assets/3844521/4d406c43-ebc2-41ee-9359-9c325ea9acd8" rel="noopener noreferrer"&gt;Streaming Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This graph explains what's going on behind the scenes. As you can see, there is a substantial gain in performance, and the user can start interacting with the page sooner, compared to SSR:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2F3b173f29-df30-42de-b5ce-5d29efc49de9" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2F3b173f29-df30-42de-b5ce-5d29efc49de9" alt="Streaming"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The skeleton is shown during a brief time interval. This is because the amount of data fetched on the server is not huge, and the connection link to the GitHub API is fast. It means that the time difference between the shell page being ready on the client (rendered on the server and then downloaded in the browser) and the RSC being ready on the client (rendered on the server and downloaded in the browser) is very small.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2Ffee44e0e-e79b-420a-b9e3-2ddeb3ecbb9e" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2Ffee44e0e-e79b-420a-b9e3-2ddeb3ecbb9e" alt="Streaming Skeleton"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PROS&lt;/strong&gt;&lt;br&gt;
✅ Always fresh data&lt;br&gt;
✅ Even better perceived performance&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MEHS&lt;/strong&gt;&lt;br&gt;
🔶 There is still a time gap between the user clicking a link and the shell page being displayed on the browser, although content chunks keep streaming&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONS&lt;/strong&gt;&lt;br&gt;
❌  By using a dynamic component, my whole page route becomes dynamic&lt;/p&gt;

&lt;p&gt;Again, the folks at Next.js put their thinking hats on and asked themselves: "&lt;em&gt;Why does the whole page route need to be dynamic?&lt;/em&gt;," "&lt;em&gt;Can't we combine the best parts of SSG for the static parts and the best parts of streaming for the dynamic ones?&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;Yes, we can. Enter Partial Pre-rendering&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Partial Pre-Rendering
&lt;/h2&gt;

&lt;p&gt;I'll quote the Vercel folks on this one:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;When you build your application, Next.js will prerender a static shell for each page of your application, leaving holes for the dynamic content. When a user visits a page, the fast static shell is served from the end-user’s nearest Edge Region, allowing the user to start consuming the page and the client and server to work in parallel. The client can start parsing scripts, stylesheets, fonts, and static markup while the server renders dynamic chunks using React’s new streaming architecture.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, the static parts of your page route are pre-rendered. This can be done at build time (SSG) or even based on revalidation frequency (ISR). Then, the dynamic parts &lt;em&gt;of the same page route&lt;/em&gt; are streamed once the initial page shell has been loaded. &lt;/p&gt;

&lt;p&gt;This is the only change I needed to make it work in my app on top of streaming. Nothing else, and you can see, it's still experimental.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;next.config.js&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/** @type {import('next').NextConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;experimental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ppr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Because the page shell has been pre-rendered, the first-page load is lightning fast as it is a pure static output &lt;a href="https://nextjs.org/docs/app/api-reference/next-config-js/assetPrefix" rel="noopener noreferrer"&gt;served from a CDN&lt;/a&gt;.  See this behavior in action in the following video:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/peibolsang/octotype/assets/3844521/4dec8aea-a160-4169-abe5-67f83b6aca9a" rel="noopener noreferrer"&gt;PPR Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compare this graph with the others above! This is really amazing:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2F913bf241-7a20-4a07-935f-51fec0bb3daf" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2F913bf241-7a20-4a07-935f-51fec0bb3daf" alt="PPR"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With PPR, the skeleton is shown during a longer interval. This is because the skeleton has been pre-rendered with the page shell and included in the static output, which means it's available at the client way sooner. This has an incredibly positive impact on perceived performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2F32b0615c-62db-4e40-a8aa-4366c59c44af" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2F32b0615c-62db-4e40-a8aa-4366c59c44af" alt="PPR Skeleton"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PROS&lt;/strong&gt;&lt;br&gt;
✅ Amazing performance, real and perceived, with always fresh data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONS&lt;/strong&gt;&lt;br&gt;
❌ It's experimental 🤷🏻‍♂️&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: SPA
&lt;/h2&gt;

&lt;p&gt;All the options described above involve some server-side rendering in one form or another with Next.js. These are all default features of the framework, which does not mean you can't do a SPA with Next.js. You can, but it isn't obvious, as it requires some additional work outside the responsibilities of the framework. &lt;/p&gt;

&lt;p&gt;Let me explain.&lt;/p&gt;

&lt;p&gt;First,  you must translate your RSC into a client component and fetch data using React classic hooks, &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt;. Nothing special here.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;components/client/user-posts.tsx&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserPostsGrid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/client/user-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUserPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/lib/api.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPosts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

    &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchedPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nf"&gt;setPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchedPosts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nf"&gt;fetchPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserPostsGrid&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserPosts&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Second, you can leave your default routing untouched using the App Router, but you need to export your application as an MPA so it can be hosted in a non-node environment, such as Amazon S3. This means you must build your application using the command &lt;code&gt;next build &amp;amp;&amp;amp; next export&lt;/code&gt;. (Remember, by default, Next.js SSG generates a node app).&lt;/p&gt;

&lt;p&gt;Third and final (and this is not trivial) because you now have an HTML file per route instead of a single &lt;code&gt;index.html&lt;/code&gt;, you need to write some custom logic to map your site routes to these different files. This can be done via a script in &lt;code&gt;nginx&lt;/code&gt; or an Edge Lambda in AWS CloudFront, but you must do it yourself. &lt;/p&gt;

&lt;p&gt;But hey, bear with me. &lt;a href="https://gist.github.com/gaearon/9d6b8eddc7f5e647a054d7b333434ef6" rel="noopener noreferrer"&gt;Dan explains this better than I do and even includes some code examples on how to do it!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what SPA processing looks like in a graph. As you can see, the client download time is still okay. Unlike other SPAs, Next.js enables &lt;strong&gt;a better SPA&lt;/strong&gt; as the client does not have to download an entire unique bundle containing the entire application. However, fetching data from the client is slower than on the server (.... at least theoretically!). In other words, it's worth analyzing the performance differences between Next.js SPA and SSR methods in detail, as differences can be minimal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2Faf303c1d-07ca-4182-9ecb-7306817ad775" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fpeibolsang%2Foctotype%2Fassets%2F3844521%2Faf303c1d-07ca-4182-9ecb-7306817ad775" alt="SPA"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;While I love frameworks that give you options, I got drunk with them. Documentation is still getting there, but the Next.js team is doing a great job creating educational material as some of these features are adopted and refined. Consequently, we are in a stage where much of the learning comes through rolling up your sleeves and start building, which is a good method anyway. And if you build in public and share your knowledge, you're contributing to improving all these features.&lt;/p&gt;

&lt;p&gt;What rendering option is better? It all depends on your application and how you manage data. For example, it wouldn't make sense always to get fresh data for a blog post because its content does not change frequently. This would make ISR a good option for this use case. On the contrary, switch to SSR or Streaming if you have a page that renders content based on data that changes very often and you always want to show it fresh on demand. Lastly, if you have a mixed page with very clear static parts that don't change often, mixed with dynamic parts that change frequently, that makes it perfect for PPR. And, to be honest, this method could even &lt;a href="https://vercel.com/blog/partial-prerendering-with-next-js-creating-a-new-default-rendering-model" rel="noopener noreferrer"&gt;become the default for many pages on many sites out there&lt;/a&gt;. And that's big.&lt;/p&gt;

&lt;p&gt;The following picture represents an overall summary of all these rendering methods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xsg4p0qafjj5056rxc8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xsg4p0qafjj5056rxc8.png" alt="All"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>My 7 favourite tenets of a good Developer Experience</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Sat, 02 Dec 2023 16:38:00 +0000</pubDate>
      <link>https://dev.to/peibolsang/my-7-favourite-tenets-of-a-good-developer-experience-1bb8</link>
      <guid>https://dev.to/peibolsang/my-7-favourite-tenets-of-a-good-developer-experience-1bb8</guid>
      <description>&lt;p&gt;After 8+ years building tools for developers, I learned that a good Developer Experience (DX) can seriously become a product differentiator, as it usually leads to a good User Experience (UX). Yes, it's all about making developers more efficient, creative, and just plain happier, but it's also about making your software products just better.&lt;/p&gt;

&lt;p&gt;I've picked up on some key things that really lift up the DX game. Today, I'm giving away my top 6 must-haves for an awesome Developer Experience in this post. These come straight from my own journey, chats with developers, and some good old community wisdom. So, whether you're deep in the code trenches, managing products, or just getting your tech feet wet, these tips could give you a perspective on the whole DX scene.&lt;/p&gt;

&lt;h1&gt;
  
  
  Values
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Liability
&lt;/h2&gt;

&lt;p&gt;Don't solve generic problems. Solve specific problems by curating technology opinions and configurations. Most of the time, you'll do it through code. Alternatively, you'll do it through documentation. You must choose what to build wisely because code is a liability, and every line of code has a maintenance cost. As a result, get ready to remove some of your developer tools over time. As things evolve and industrialize, you must find your core values and lean on third-party libraries and cloud services.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Simplicity
&lt;/h2&gt;

&lt;p&gt;Don't try to build magical tools that turn complex problems into easy ones. That can't happen. Instead, it's better to provide tools to make it easier for developers to deal with the complexity without hiding the essential details of such complexity.&lt;/p&gt;

&lt;h1&gt;
  
  
  Principles
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Low cognitive load
&lt;/h2&gt;

&lt;p&gt;Developer tools should not get in the way of developers. Good tools let developers keep with their train of thought easily without distracting them. There are no mental gymnastics needed to solve a problem. None. Your tools must let developers maximize their moments of inspiration.&lt;/p&gt;

&lt;p&gt;The mental model a good tool pushes to developers is lightweight. There is no magic, and developers must still feel in control. Recognizing that engineering cycles are scarce, you should create functionality that does one thing, and does it well, giving developers time and space to focus on fixing those complex problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Abstractions, not illusions
&lt;/h2&gt;

&lt;p&gt;Reducing the developer's cognitive load does not involve taking as many things away as possible. You don’t want to turn your abstractions into compositions or orchestrations of multiple solutions because that leads to unexpected surprises. Developers must know and understand what they are doing; therefore, you shouldn't hide essential details of what you are abstracting away. Abstractions should adhere to the "principle of less surprise," so developers must know at every moment what is happening when they work with your abstractions.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Leaky abstractions
&lt;/h2&gt;

&lt;p&gt;A corollary of the above principle is that you should do “just enough encapsulations.” Creating non-added value wrappers on top of standard libraries and functionalities is a smell. Make sure your developers build on standard technologies (libraries or cloud services) with the help of your tools instead of building on your tools.&lt;/p&gt;

&lt;p&gt;This means that your tools should not save developers from knowing things. Build functionalities that minimize how much a new developer has to know to start shipping (with default configurations or conventions) but provide a pathway to go deeper over time. The underlying technology should be exposed as a peer dependency so users can become experts about it through your tooling over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. (Not too much) inversion of control
&lt;/h2&gt;

&lt;p&gt;Focus on building primitives for developers (building blocks and examples), and be wary of creating generic frameworks (overarching and locked-down tools). If you create a framework, ensure it addresses a particular problem. &lt;a href="https://www.youtube.com/watch?t=1906&amp;amp;v=anr7DQnMMs0&amp;amp;feature=youtu.be"&gt;In the words of PHP creator Ramus Lerdorf&lt;/a&gt;: “&lt;em&gt;Everyone needs a framework; what everyone doesn't need is a general purpose framework. Nobody has a general problem; everyone has a specific one they're trying to solve.&lt;/em&gt;”&lt;/p&gt;

&lt;h2&gt;
  
  
  5. No “one-size-fits-all” abstractions
&lt;/h2&gt;

&lt;p&gt;Once you have decided to create an abstraction, it can't be all things to all people. It's okay for your developer tools to offer different functionalities in different levels of abstraction for the same persona (e.g., a frontend developer), depending on their needs. However, you should not create one level of abstraction to serve all needs for the same persona.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>coding</category>
      <category>architecture</category>
    </item>
    <item>
      <title>The Frontend Cloud</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Sun, 16 Apr 2023 16:27:14 +0000</pubDate>
      <link>https://dev.to/peibolsang/the-frontend-cloud-f5g</link>
      <guid>https://dev.to/peibolsang/the-frontend-cloud-f5g</guid>
      <description>&lt;p&gt;The landscape of Web dev tech has been oscillating between the "all server" and "all client" models, with each phase presenting its unique set of advantages and challenges. Now, this swinging pendulum is losing momentum and reaching a point of equilibrium (&lt;em&gt;how did I manage to write three Latin words in 1 sentence?&lt;/em&gt;). Where's this equilibrium happening? At the center, obviously. Where is the center, though? &lt;strong&gt;At the edge&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The latest innovations introduced by React-based frameworks such as Next.js and Remix and cloud platforms such as Vercel and Netlify are giving birth to a groundbreaking architectural hybrid model. This architecture is The Frontend Cloud, and it leverages the advancements in Edge Cloud computing and Content Delivery Networks (CDNs) to enhance Web development capabilities significantly. Concretely speaking, The Frontend Cloud leans on the CDN's new computing and storage capabilities, something unimaginable until very recently.&lt;/p&gt;

&lt;p&gt;In this post, I will delve into the intricacies of thi model and analyze its potential in reshaping the web development domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Foundation: Edge Runtimes and CDN
&lt;/h2&gt;

&lt;p&gt;Edge Computing and CDNs are at the core of the Frontend Cloud model, which represents a significant departure from traditional cloud infrastructure running in data center regions. Edge computing enables the execution of server-side logic closer to the end-users in &lt;strong&gt;geographical edge regions&lt;/strong&gt;, substantially improving response times and reducing latency. &lt;/p&gt;

&lt;p&gt;However, edge &lt;em&gt;the location&lt;/em&gt; is less important than edge &lt;em&gt;the runtime&lt;/em&gt; when it comes to this idea of the Frontend Cloud. Therefore, most Cloud Computing providers allow developers to run workloads on &lt;em&gt;edge runtimes&lt;/em&gt;. These are basically Javascript runtimes, such as V8, Node.js, or &lt;a href="https://deno.com/deploy"&gt;Deno&lt;/a&gt;. Why is that? Well, there are many reasons, but performance and security are chief among them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For example, the V8 JavaScript engine supports the concept of "isolates," which are separate instances of the V8 runtime that share no memory or resources with each other. This isolation significantly reduces the risk of cross-script vulnerabilities, data leaks, or unauthorized access to sensitive information.&lt;/li&gt;
&lt;li&gt;Running JavaScript in isolated sandboxes allows granular control over resources and permissions. Developers can explicitly define the resources, data, and I/O API access available to each sandbox, limiting the potential impact of security vulnerabilities or breaches&lt;/li&gt;
&lt;li&gt;JavaScript is inherently suited for handling event-driven and non-blocking I/O operations, thanks to its asynchronous nature and single-threaded execution model. These characteristics make JavaScript an excellent fit for edge computing scenarios, where efficiently handling multiple concurrent requests is critical to achieving low latency and high performance.&lt;/li&gt;
&lt;li&gt;WASM 😇&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This ability to perform computations at the edge of the network, coupled with the dynamic content delivery capabilities of CDNs, has contributed to the genesis of the Frontend Cloud model.&lt;/p&gt;

&lt;p&gt;Notable services like Cloudflare Workers and Vercel Edge Functions have already demonstrated the potential of the Frontend Cloud model with cool features such as &lt;a href="https://beta.nextjs.org/docs/data-fetching/streaming-and-suspense"&gt;HTTP Streaming, which, in combination with React's Supense API and Server Components&lt;/a&gt;, are paving the way for the development of lightning-fast, resource-efficient web applications. Moreover, CDNs now support ephemeral storage through Key-Value (KV) objects, further extending the server-side logic capabilities to run even more complex business logic!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Limitations of Current Edge Technologies
&lt;/h2&gt;

&lt;p&gt;Despite the numerous advantages of the Frontend Cloud model, we need to be aware of a good number of limitations. One key issue I see is the absence of global replication for KV objects. At present, KV objects are localized to the edge location, restricting their utility for global use cases. However, the introduction of solutions such as Cloudflare's Durable Objects seeks to address this challenge by offering global replication, although the technology is still in its infancy. Overcoming these limitations will be crucial for the widespread adoption of the Frontend Cloud model.&lt;/p&gt;

&lt;p&gt;The rapid evolution of Edge Cloud computing and the introduction of the Frontend Cloud architecture suggests that web development will continue to experience remarkable transformations in the coming years. I am very excited about solutions like &lt;a href="https://upstash.com/blog/redis-cloudflare-workers"&gt;Radis on the CDN&lt;/a&gt; or even &lt;a href="https://neon.tech/"&gt;Neon Database&lt;/a&gt;, which opens the possibility of performing PostgreSQL read/write operations on the CDN, something that could happen within the next few years. Such advancements would pave the way for the development of web applications with greater flexibility, reliability, and performance.&lt;/p&gt;

&lt;p&gt;As the Frontend Cloud model evolves, we can anticipate the creation of new web development tools and technologies that streamline the development process. Real-time data synchronization and adaptive server-side rendering are just a few examples of the innovations that will emerge from this new paradigm. Consequently, web applications will become increasingly versatile, allowing seamless operation across multiple devices and platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Despite the promise of the Frontend Cloud model, several challenges must be addressed before it can achieve its full potential. Latency, data consistency, and security concerns are among the most pressing issues that need to be resolved to ensure the successful adoption of the Frontend Cloud model. As innovators in this emerging field, it is imperative that we collaborate and share our collective knowledge to tackle these challenges and unlock the true potential of the Frontend Cloud.&lt;/p&gt;

&lt;p&gt;The Frontend Cloud model, with its unique fusion of server and client-side capabilities, has the potential to revolutionize the web development landscape. By harnessing the power of Edge Cloud and CDNs, web developers can create high-performance, adaptive, and immersive experiences for users across the globe. As the limitations of the current Edge technologies are addressed and overcome, the Frontend Cloud model will continue to mature and reshape the boundaries of web development.&lt;/p&gt;

&lt;p&gt;Look at the following piece of code using Next.js and Planetscale:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xzNimgbk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l2y54v76xdvfy9axq0ky.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xzNimgbk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l2y54v76xdvfy9axq0ky.jpeg" alt="Image description" width="800" height="1106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking closely at the code, you may think we are reinventing PHP. However, I like to see this differently. Indeed the server-side code looks like PHP, and the client-side code looks like a SPA. But isn't that the magic? I love how I can combine server efficiency and client reactivity in one app.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>cloud</category>
    </item>
    <item>
      <title>It's time to rename serverless</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Wed, 22 Mar 2023 08:32:06 +0000</pubDate>
      <link>https://dev.to/peibolsang/its-time-to-rename-serverless-3ljn</link>
      <guid>https://dev.to/peibolsang/its-time-to-rename-serverless-3ljn</guid>
      <description>&lt;p&gt;This is a short post.&lt;/p&gt;

&lt;p&gt;The theory of Wardley mapping talks about how things get a new meaning as they evolve.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DevOps does not mean the same in 2023 as in 2013&lt;/li&gt;
&lt;li&gt;Cloud does not mean the same in 2023 as in 2010&lt;/li&gt;
&lt;li&gt;Platform does not mean the same in 2023 as in 2000&lt;/li&gt;
&lt;li&gt;Serverless does not mean the same in 2023 as in 2016&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let me go back to some basics.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the cloud?
&lt;/h2&gt;

&lt;p&gt;The concept of the cloud started as industrialized, interoperable, and commoditized infrastructure services built on standards and distributed over the wire to users. Today, the concept of cloud expanded this definition to include the idea of a system made of services, features, and principles that work in harmony to allow users to &lt;em&gt;build the thing right&lt;/em&gt;. With this definition, the value proposition of cloud platforms is about meeting business leading goals such as speed of development, reliability, security, agility, and efficiency. &lt;/p&gt;

&lt;p&gt;In 2023, we have three different levels of services offered by cloud platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Infrastructure services&lt;/strong&gt;: this collection of services and features are basically VMs offered as a service. Example: Amazon EC2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Runtime services&lt;/strong&gt;: this collection of services and features are runtimes offered as a service. Example: AWS Lambda.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Application services&lt;/strong&gt;: this collection of services and features are applications offered as a service. Example: Salesforce CRM.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The thing is that, in 2023, you don't need to own a data center and distribute infrastructure as pay-per-use services to be a cloud provider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fly.io is a cloud provider of infrastructure services&lt;/li&gt;
&lt;li&gt;Vercel and Supabase are cloud providers for runtime services&lt;/li&gt;
&lt;li&gt;Atlassian is a cloud provider of application services&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is content?
&lt;/h2&gt;

&lt;p&gt;Content is the collection of things that platform users own and put in the platform to &lt;em&gt;build the right thing&lt;/em&gt;. Content's value proposition is about meetings meeting business lagging goals such as growth, revenue, and customer satisfaction. In other words, content is defined by what the user owns on the platform.&lt;/p&gt;

&lt;p&gt;We have different types of content depending on the services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For infrastructure services&lt;/strong&gt;: the user owns the runtimes, code, and data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For runtime services&lt;/strong&gt;: the user owns the code and data. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For application services&lt;/strong&gt;: the user only owns the data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is serverless, then?
&lt;/h2&gt;

&lt;p&gt;The concept of serverless started as &lt;em&gt;on-demand functions&lt;/em&gt; thanks to services to Google AppEngine and AWS Lambda. Today, we can find complex definitions that include a combination of &lt;em&gt;Functions as a Service&lt;/em&gt; and &lt;em&gt;Backend as a Service&lt;/em&gt;, especially since the introduction of serverless containers. To me, the concept of serverless in 2023 evolved to &lt;strong&gt;runtimes as a service&lt;/strong&gt; that scale to zero where users own the code and the data. It is that simple.&lt;/p&gt;

&lt;p&gt;So, the moment I see a new service out there, I ask myself two questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What do I own?&lt;/li&gt;
&lt;li&gt;How does it scale?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on the answer to these two questions, I mentally categorize the type of platform I am working with. The moment I own code and data and the service scales to zero, I know I am using Runtime as a Service, and I am conscious of my duties, including what I am responsible for upgrading and maintaining! Some people call this serverless 🫠&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Conversational Programming</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Tue, 10 Jan 2023 08:19:13 +0000</pubDate>
      <link>https://dev.to/peibolsang/conversational-programming-4l53</link>
      <guid>https://dev.to/peibolsang/conversational-programming-4l53</guid>
      <description>&lt;p&gt;I heard multiple times Simon Wardley talking about &lt;a href="https://twitter.com/swardley/status/1102889853954478080?s=20&amp;amp;t=8URYAKOdTYQ1kMx1ZCw1Tw" rel="noopener noreferrer"&gt;Conversational Programming as far back as 2019&lt;/a&gt;, but I think it didn't strike me until I put my hands on it. Yes, as I have shared in this post, &lt;a href="https://octotype.vercel.app/peibolsang/stories/2" rel="noopener noreferrer"&gt;I used ChatGPT to generate about 30%-40% of the code I wrote for octotype&lt;/a&gt;, and I am still in awe.&lt;/p&gt;

&lt;p&gt;Something I noticed is that the model behind ChatGPT is &lt;em&gt;good enough&lt;/em&gt; to interpret semi-ambiguous requirements but still needs a considerable deal of &lt;em&gt;detailed&lt;/em&gt; input that expresses my intent. The same happened when &lt;a href="https://twitter.com/peibolsang/status/1606318579506454528?s=20&amp;amp;t=RK9Mnof0VooVX8wSUScJHA" rel="noopener noreferrer"&gt;I re-trained a Stable Diffusion model with selfies to generate cyberpunk-like portraits of myself&lt;/a&gt;. That type of thought process to express intent and reduce uncertainty in the input is what many people call &lt;strong&gt;Prompt Engineering&lt;/strong&gt;. However, I think this is precisely what Simon Wardley calls &lt;strong&gt;Conversational Programming&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In other words, Prompt Engineering looks a lot like Programming. When you are programming, there is a process to remove ambiguity and uncertainty, so your intent is understood by the machine, and you express that intent in a language that the machine understands, such as Javascript. Well, that's precisely what we are doing with these AI models, but instead of using a 4GL programming language, we are using our Natural Language.&lt;/p&gt;

&lt;p&gt;I said it multiple times, but when you automate something (with AI or otherwise), you are actually &lt;strong&gt;constraining that something with automation&lt;/strong&gt;, and you can only constrain something with very low levels of uncertainty. Unfortunately, high-level business requirements to create software are not something that you can automate in full. You still need a process to remove ambiguity and express your intent, and you need to do it iteratively.  You still need to divide and break down your big &lt;em&gt;uncertain problem&lt;/em&gt; into smaller, more certain chunks expressed in natural language. Basically, you are programming conversationally.&lt;/p&gt;

&lt;p&gt;Maybe, in time, these models get more intelligent so that they offer higher-level abstractions for us to ease the process of removing ambiguity and expressing intent. That is precisely what happened when we moved from assembly to Java! In other words, we may be at the doorstep of a new generation (5GL) of programming languages based on problem-solving using constraints given to the machines rather than commands.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>api</category>
      <category>serverless</category>
    </item>
    <item>
      <title>I created my own blog platform with Next.js, GitHub Issues and OpenAI in 2 days</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Mon, 02 Jan 2023 16:59:23 +0000</pubDate>
      <link>https://dev.to/peibolsang/i-created-my-own-blog-platform-with-nextjs-github-issues-and-openai-in-2-days-50ff</link>
      <guid>https://dev.to/peibolsang/i-created-my-own-blog-platform-with-nextjs-github-issues-and-openai-in-2-days-50ff</guid>
      <description>&lt;h2&gt;
  
  
  What happened?
&lt;/h2&gt;

&lt;p&gt;Those who know me (or have been following me for a while) know that I love writing. I find it a liberating experience, and it has enormously helped me sort and then consolidate thoughts in my head for years. I am okay with it if no one reads my content; for me, this is more of a &lt;em&gt;learning in-public&lt;/em&gt; exercise, and somehow I consider my blog posts as personal rants sometimes! Yes, &lt;a href="https://dev.to/peibolsang"&gt;I write a lot&lt;/a&gt;, to the extent that I have compiled years' worth of personal notes while I worked on an incredibly challenging cloud product and published them as a book (go check out &lt;a href="https://leanpub.com/software-platforms" rel="noopener noreferrer"&gt;Building Software Platforms!&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;For a while now, I have been considering running my own blog as an investment in my personal branding. Note that I said "running," not "hosting." As you know, I am a firm believer in SaaS, frontend cloud platforms, serverless, and everything that distills the spirit of treating software as a liability. In part because I am a terribly bad programmer 😇.&lt;/p&gt;

&lt;p&gt;I find modern blogging platforms very compelling, but as I said, I wanted to double down on my personal branding without entering into too much development and maintenance costs. It's a sound tradeoff for someone like me, isn't it? &lt;a href="https://twitter.com/peibolsang/status/1387894516108103681?s=20&amp;amp;t=GYPC-f0Tt-sr7iSz4dH9lA" rel="noopener noreferrer"&gt;I considered some options in the past using GitHub Gists&lt;/a&gt; but it was &lt;a href="https://twitter.com/swyx/status/1480356418817753088?s=20&amp;amp;t=GYPC-f0Tt-sr7iSz4dH9lA" rel="noopener noreferrer"&gt;this post from Swyx that really triggered my curiosity&lt;/a&gt;. Yes, using GitHub issues as a CMS and building a small frontend on top sounds like an endeavor I can afford!&lt;/p&gt;

&lt;h2&gt;
  
  
  How did I do it?
&lt;/h2&gt;

&lt;p&gt;First of all, being a terribly bad programmer as I am, I wanted to minimize damage and use a stack that maximizes the developer experience. For me, a good developer experience provides the tools that create spaces for you to focus on fixing the business problem at hand. It's not about magic tools that do hundred of things. That's why the following stack fits the bill for me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;GitHub Issues as CMS&lt;/strong&gt; 📚. GitHub's Issue management system gives me all I need to create and manage content behind the scenes. I am very familiar with it, and it's easy to use, widely adopted, and has an out-of-the-box API with a good free tier. It's just perfect!&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Next.js with the Blog template&lt;/strong&gt; ✍🏻. My new blog site is leaning heavily on this template, and I only added a few new types, components, and UI functionality to fetch data from GitHub through its API, such as issues (as posts), comments, and reactions. Of course, it's a statically generated site, but I have used &lt;a href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration" rel="noopener noreferrer"&gt;Incremental Site Regeneration&lt;/a&gt;, so new issues created in GitHub Issues show up as blog posts after a very short while. It's just perfect &lt;strong&gt;and lightning fast&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typescript&lt;/strong&gt; 💻. I feel very comfortable programming with types. I think it forces you into a kind of healthy DDD thinking and way of programming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel as frontend platform&lt;/strong&gt; 🚀. &lt;a href="https://peibolsang.vercel.app/posts/2" rel="noopener noreferrer"&gt;Nothing to add, you know I am in love with Vercel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI&lt;/strong&gt; 🤖.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wait, OpenAI? For what? Well, building the whole new site took me about two (2) days. Seriously. It may not sound like a lot to you, but it's a remarkable achievement for someone like me who does not code daily. I have used it extensively to customize the app created from the Next.js template, and ChatGPT helped me immensely to write Tailwind, Typescript, and other Next.js code when I hit a wall. This was one of the main reasons I wanted to build my own site: with this tool, I felt capable of doing something like this in a reasonable time for the first time in a while.&lt;/p&gt;

&lt;p&gt;But there is more. Do you see the post excerpts on the landing page? &lt;strong&gt;I have used OpenAI API to generate these summaries of my blog posts and add them as excerpts&lt;/strong&gt;. I am just testing this feature, and I believe this is going to work for a while until OpenAI starts to charge me. At that moment, I will probably replace this functionality with a dumb excerpt generator.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I am super happy with the result and super proud of my work (or should I say AI's work?). I think this is a good MVP, but I can think of a few features down the road:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better responsiveness for certain pages&lt;/li&gt;
&lt;li&gt;Hashtags and search&lt;/li&gt;
&lt;li&gt;Dark mode&lt;/li&gt;
&lt;li&gt;.... &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And probably nothing else? This is a blog site, so I don't want features creeping over here. I want it to be fast, and I want it to be simple. And so far, this is what I have done. &lt;/p&gt;

&lt;p&gt;I think I'm going to give it a try for a long while!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Cover photo credits: Andrew Neel via Unsplash)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Why I always favor Serverless over Kubernetes</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Thu, 29 Dec 2022 20:17:04 +0000</pubDate>
      <link>https://dev.to/peibolsang/why-i-will-always-favor-serverless-over-kubernetes-j9o</link>
      <guid>https://dev.to/peibolsang/why-i-will-always-favor-serverless-over-kubernetes-j9o</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Wait, before you go and pitch your boss on ditching your current setup in favor of serverless without knowing all the details, let's talk about the other player in town first: Kubernetes. Kubernetes (or K8s, as the cool kids call it) has gained a lot of popularity in recent years as a container orchestration platform. It's definitely a powerful tool and has its place in the world of cloud computing. But is it the right fit for your needs?&lt;/p&gt;

&lt;p&gt;In this blog post, we're going to compare serverless and Kubernetes and try to answer that question. We'll go over the benefits of both and help you understand when it makes sense to use one over the other. And, just to keep things interesting, we'll even throw in some jokes along the way (because seriously, cloud computing doesn't have to be so serious all the time).&lt;/p&gt;

&lt;p&gt;So, let's dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Serverless Computing?
&lt;/h2&gt;

&lt;p&gt;First things first, let's define what we're talking about when we say "serverless computing." Serverless computing is a cloud computing execution model in which the cloud provider dynamically allocates resources to run an application's code in response to incoming requests or events. This means that the developer doesn't have to worry about provisioning or maintaining servers – they can just focus on writing code that runs in response to certain triggers.&lt;/p&gt;

&lt;p&gt;One of the main benefits of serverless computing is that it allows for a pay-per-use model. You only pay for the resources consumed while running the code, which can result in significant cost savings compared to traditional cloud computing models (where you pay for resources even when they're not being used). Because in many ways, having a friend with a boat is much better than owning a boat!&lt;/p&gt;

&lt;p&gt;Serverless computing also allows for faster deployment and scalability. Since the cloud provider is responsible for managing the underlying infrastructure, it's much easier to deploy and scale applications without having to worry about capacity planning or resource allocation. It's like having your own personal cloud genie – just snap your fingers and boom, your application is deployed and scaling like magic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Now, let's talk about Kubernetes. Kubernetes is an open-source container orchestration platform that was originally developed by Google. It allows you to automate the deployment, scaling, and management of containerized applications.&lt;/p&gt;

&lt;p&gt;In a Kubernetes setup, you create "pods" that contain one or more containers. These pods can then be scaled up or down based on the needs of your application. Kubernetes also provides features for load balancing and rolling updates, so you can update your application without any downtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, What's the Verdict? Serverless or Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Ok, now for the big question: which one is better? As with most things in life, the answer is "it depends." Both serverless and Kubernetes have their own unique benefits and drawbacks, and the right choice will depend on your specific needs and goals.&lt;/p&gt;

&lt;p&gt;That being said, there are a few key differences between the two that might help you make your decision.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplified Architecture&lt;/strong&gt;: With serverless computing, the developer doesn't have to worry about the underlying infrastructure or the management of containers. This simplifies the architecture of the application, allowing the developer to focus on writing code that runs in response to certain triggers. Kubernetes, on the other hand, requires a bit more setup and management. You have to worry about creating and scaling pods, as well as monitoring and maintaining the underlying infrastructure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pay-Per-Use Model&lt;/strong&gt;: As we mentioned earlier, serverless computing offers a pay-per-use model, where you only pay for the resources consumed while running the code. This can be a big cost savings compared to traditional cloud computing models. Kubernetes, on the other hand, operates on a more traditional model, where you pay for the resources you use, regardless of whether your code is running or not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Faster Deployment and Scalability&lt;/strong&gt;: As we mentioned earlier, serverless computing allows for faster deployment and scalability, as the cloud provider is responsible for managing the underlying infrastructure. Kubernetes also allows for fast deployment and scaling, but you have to manage the underlying infrastructure yourself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with Cloud Services&lt;/strong&gt;: Many cloud providers offer a wide range of services that can be easily integrated with serverless applications, such as databases, message queues, and analytics tools. This allows for the creation of highly scalable and performant applications with minimal effort. Kubernetes also allows for integration with various cloud services, but it requires a bit more setup and management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Security&lt;/strong&gt;: With serverless computing, the developer doesn't have to worry about patching and updating the underlying infrastructure, as the cloud provider is responsible for this. This can improve the overall security of the application, as it reduces the attack surface and ensures that the infrastructure is always up to date. Kubernetes also offers various security features, but the developer is responsible for managing and maintaining them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, as you can see, both serverless and Kubernetes have their own benefits and drawbacks. It's up to you to decide which one is the right fit for your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  But Wait, There's More!
&lt;/h2&gt;

&lt;p&gt;Of course, there's much more to consider when choosing between serverless and Kubernetes. Here are 17 advanced concepts every software engineer should know about serverless&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event-Driven Architecture&lt;/strong&gt;: Serverless computing relies on an event-driven architecture, where the code is executed in response to certain triggers, such as incoming HTTP requests, database updates, or the arrival of new data in a message queue. It is important for software engineers to understand how to design and build applications using this architecture, and to be familiar with the various types of triggers that are available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Function as a Service (FaaS)&lt;/strong&gt;: Serverless computing relies on the concept of "functions as a service," or FaaS, where individual pieces of code are executed in response to certain triggers. It is important for software engineers to understand how to write and deploy these functions, and to be familiar with the various frameworks and platforms that are available, such as AWS Lambda, Azure Functions, and Google Cloud Functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cold Start Latency&lt;/strong&gt;: One of the challenges of serverless computing is the potential for cold start latency, where it takes longer for a function to execute when it has not been recently used. It is important for software engineers to understand how to minimize this latency, and to be familiar with the various techniques that can be used, such as keeping functions warm or using a higher memory allocation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scaling&lt;/strong&gt;: With serverless computing, the cloud provider is responsible for scaling the application based on the incoming traffic. It is important for software engineers to understand how this scaling works, and to be familiar with the various tools and techniques that can be used to optimize it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitoring and Debugging&lt;/strong&gt;: With serverless computing, the cloud provider is responsible for managing the underlying infrastructure, which can make it more difficult to monitor and debug issues. It is important for software engineers to be familiar with the various tools and techniques that can be used to monitor and debug serverless applications, such as cloud provider logs, APM tools, and debugging tools like AWS X-Ray.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Management&lt;/strong&gt;: With traditional cloud computing, it is easy to store state in a database or on the filesystem of a server. With serverless computing, this becomes more challenging, as the underlying infrastructure is ephemeral and the code is executed in response to certain triggers. It is important for software engineers to understand how to manage state in a serverless environment, and to be familiar with the various options that are available, such as using a database or using a cache like Redis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with Third-Party Services&lt;/strong&gt;: One of the benefits of serverless computing is the ability to easily integrate with a wide range of third-party services, such as databases, message queues, and analytics tools. It is important for software engineers to understand how to integrate these services into a serverless application, and to be familiar with the various APIs and SDKs that are available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;: With serverless computing, the developer does not have to worry about patching and updating the underlying infrastructure, as the cloud provider is responsible for this. However, it is still important for software engineers to understand how to secure a serverless application, and to be familiar with the various best practices and tools that are available, such as using encryption and implementing proper access controls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cost Optimization&lt;/strong&gt;: One of the benefits of serverless computing is the pay-per-use model, where the developer only pays for the resources consumed while running the code. It is important for software engineers to understand how to optimize costs in a serverless environment, and to be familiar with the various tools and techniques that can be used, such as using reserved instances or optimizing the memory allocation of functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CI/CD&lt;/strong&gt;: With serverless computing, it is important to have a robust CI/CD pipeline in place to ensure that code is deployed quickly and efficiently. It is important for software engineers to be familiar with the various tools and techniques that can be used to automate the deployment of serverless applications, such as using a deployment platform like AWS CodePipeline or using a serverless framework like Serverless.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Serverless Frameworks&lt;/strong&gt;: There are various frameworks available that can help software engineers build and deploy serverless applications more easily. These frameworks typically provide a set of tools and libraries that can be used to define and deploy functions, as well as handle tasks like scaling, monitoring, and deployment. Some examples of popular serverless frameworks include AWS SAM, Serverless, and OpenFaaS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event-Driven Data Processing&lt;/strong&gt;: Serverless computing is well-suited for event-driven data processing, where data is processed in real-time as it is generated. It is important for software engineers to understand how to design and build applications that can handle this type of data processing, and to be familiar with the various tools and techniques that can be used, such as using a message queue or a stream processing platform like Apache Kafka or AWS Kinesis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Microservices&lt;/strong&gt;: Serverless computing is often used to build microservices architectures, where an application is composed of multiple independent services that communicate with each other using APIs. It is important for software engineers to understand how to design and build microservices using serverless computing, and to be familiar with the various tools and techniques that can be used to manage and deploy these services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with Server-Based Applications&lt;/strong&gt;: While serverless computing is well-suited for building cloud-native applications, it can also be used to integrate with existing server-based applications. It is important for software engineers to understand how to integrate serverless functions with these types of applications, and to be familiar with the various tools and techniques that can be used, such as using a reverse proxy or an API gateway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hybrid Architectures&lt;/strong&gt;: It is possible to build hybrid architectures that combine serverless computing with traditional cloud computing or on-premises infrastructure. It is important for software engineers to understand how to design and build these types of architectures, and to be familiar with the various tools and techniques that can be used to manage and deploy them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Serverless Patterns&lt;/strong&gt;: There are various patterns and best practices that have been developed for building serverless applications. It is important for software engineers to be familiar with these patterns, and to understand how to apply them to different types of projects. Some examples of common serverless patterns include the Fan-Out pattern, the Command Query Responsibility Segregation (CQRS) pattern, and the Event Sourcing pattern.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Serverless Limitations&lt;/strong&gt;: While serverless computing has many benefits, it is not a panacea and there are certain limitations that software engineers should be aware of. It is important to understand when it is appropriate to use serverless computing, and to be familiar with the various trade-offs and limitations that come with it, such as cold start latency and the potential for vendor lock-in.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So, there you have it – a comparison of serverless and Kubernetes. As we mentioned earlier, the right choice will depend on your specific needs and goals. Both serverless and Kubernetes have their own unique benefits and drawbacks, and it's up to you to decide which one is the best fit for your project.&lt;/p&gt;

&lt;p&gt;We hope this blog post has helped you understand the differences between serverless and Kubernetes, and has given you a better idea of which one is right for you. Remember, there's no one-size-fits-all solution when it comes to cloud computing, and it's important to consider the pros and cons of each option before making a decision.&lt;/p&gt;

&lt;p&gt;But hey, don't stress too much about it. After all, we're just talking about cloud computing – it's not like anyone's life is on the line here. Just do your due diligence and choose the option that makes the most sense for your project. Happy cloud computing!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(&lt;a href="https://twitter.com/peibolsang"&gt;Follow me on Twitter&lt;/a&gt; to keep the discussion going!)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>kubernetes</category>
      <category>k8s</category>
      <category>cloud</category>
    </item>
    <item>
      <title>What's next after serverless?</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Thu, 08 Dec 2022 16:32:47 +0000</pubDate>
      <link>https://dev.to/peibolsang/whats-next-after-serverless-4630</link>
      <guid>https://dev.to/peibolsang/whats-next-after-serverless-4630</guid>
      <description>&lt;h2&gt;
  
  
  Primitives and Frameworks
&lt;/h2&gt;

&lt;p&gt;We have heard many times that AWS builds primitives, not frameworks. But, what does that mean? For starters, here is my own definition of the terminology:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Primitives&lt;/strong&gt; are low-level, highly-reusable building blocks with high &lt;a href="https://kentcdodds.com/blog/inversion-of-control" rel="noopener noreferrer"&gt;Inversion of Control&lt;/a&gt;​. With primitives, we give developers the power to implement their use cases​ and solve business problems while we don't leave them alone. We present them with added-value tools​ such as UI Components, APIs, or SDKs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Frameworks&lt;/strong&gt;, on the contrary, are high-level abstractions that encapsulate concrete and particular use cases. These solutions take longer to build because you are locking down a concrete use case​, even for a concrete persona. That use case is only modifiable via the predicted API of the abstraction you are building, such as smart UI components pre-connected to the backend, low-code tools, or even configurable apps (the highest-level software abstraction possible!)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are AWS execs really committed to this vision of building primitives only? Of course, they are. After another year of AWS re:Invent, we can see how AWS doubles down on this strategy by introducing new primitives (&lt;a href="https://aws.amazon.com/blogs/aws/introducing-vpc-lattice-simplify-networking-for-service-to-service-communication-preview/" rel="noopener noreferrer"&gt;AWS VPC Lattice&lt;/a&gt;) and evolving the existing ones (e.g., &lt;a href="https://aws.amazon.com/blogs/aws/new-accelerate-your-lambda-functions-with-lambda-snapstart/" rel="noopener noreferrer"&gt;AWS Lambda SnapStart&lt;/a&gt;), especially around serverless. It looks to me that adding the &lt;em&gt;serverless&lt;/em&gt; identifier to an existing service name is a safe path to innovation (and survival) at AWS in this difficult times. I have no other explanation. How else can you say that new services such as &lt;a href="https://aws.amazon.com/blogs/aws/preview-amazon-opensearch-serverless-run-search-and-analytics-workloads-without-managing-clusters/" rel="noopener noreferrer"&gt;AWS OpenSearch Serverless&lt;/a&gt; are serverless? This one is far from the first principles of usage-based pricing without minimums.&lt;/p&gt;

&lt;p&gt;All this made me think. What happens when all AWS services have a serverless flavor? What's next after serverless?&lt;/p&gt;

&lt;p&gt;We can look a this from 2 perspectives.&lt;/p&gt;

&lt;h2&gt;
  
  
  A cloud provider perspective
&lt;/h2&gt;

&lt;p&gt;We call &lt;em&gt;The Cloud&lt;/em&gt; a set of industrialized infrastructure and computing services offered as commodities you can subscribe to. This definition includes serverless computing, which is nothing but "runtime as a service" where the cloud provider owns the infrastructure and runtimes, and the customer owns the application data and code.&lt;/p&gt;

&lt;p&gt;Will AWS (or any other &lt;em&gt;cloud provider&lt;/em&gt;) ever go up the stack and own the application data and code? No, it's implausible that they enter the SaaS space with out-of-the-box applications, leaving their platform business model behind. As masters of industrialization, I can see AWS in the foreseeable future commoditizing all aspects of modern computing until they reach the highest level of abstraction possible according to its vision. What is this level? Remember, they don't build frameworks, so don't expect them to create new services that lock down specific use cases to help developers build a particular type of application. Instead, they make primitives, so expect new cloud computing services arriving to disruptive fields such as &lt;a href="https://www.allthingsdistributed.com/2022/12/tech-predictions-for-2023-and-beyond.html" rel="noopener noreferrer"&gt;AI and simulated worlds&lt;/a&gt;, some of them with all kinds of &lt;em&gt;serverless&lt;/em&gt; identifiers in their names. Also, expect improved documentation, refined APIs, and better pricing schemes.&lt;/p&gt;

&lt;p&gt;In a nutshell, what's next after serverless for them? Nothing, they will keep industrializing computing services. Serverless is the end game for hyperscale cloud providers such as AWS, Google Cloud or Microsoft Azure.&lt;/p&gt;

&lt;p&gt;Well, there is one path I believe they would eventually test deeper: the idea of &lt;em&gt;distributed provisioning with centralized control&lt;/em&gt;. This is about pushing the cloud limits to the edge, where the edge is actually &lt;em&gt;any&lt;/em&gt; piece of infrastructure closest to the user, even if that piece is self-managed by them. In other words, this is like transforming your own datacenter in a custom AWS cloud region. We can now say that &lt;a href="https://aws.amazon.com/blogs/containers/introducing-amazon-ecs-anywhere/" rel="noopener noreferrer"&gt;AWS ECS Anywhere&lt;/a&gt; was a shy attempt to test these waters, as we didn't see much traction from AWS evolving this family of services.&lt;/p&gt;

&lt;h2&gt;
  
  
  A niche player perspective
&lt;/h2&gt;

&lt;p&gt;With all the above, there seems to be a business case for niche players. There is an opportunity now to build frameworks that lock down concrete use cases that solve specific problems for developers when they are building serverless applications. You know, AWS would never do it ... and they should not, &lt;a href="https://twitter.com/jeremy_daly/status/1474110290874753030?s=20&amp;amp;t=6cM6juM_IoTKCfI43dQILw" rel="noopener noreferrer"&gt;as Jeremy points out in this thread&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Okay, but what are these problems? Let me tell you: problem number one is (poor) &lt;strong&gt;serverless development experience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One issue that I hear often is that when you are building serverless applications, you don't have a clear view of what services you are using. It's difficult to find your stuff. I've even listened to a few developers claiming that &lt;em&gt;"with monolithic and serverful architectures, I know all the frameworks and technology I am using just by looking at the project structure in VS Code"&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;In the early days of serverless, my answer was: &lt;em&gt;"When you are building a serverless app, that view is provided by the AWS console. You can see all you need there!"&lt;/em&gt;. Almost. Now I reckon my answer was not very satisfactory and those developers still had a point. It's all too scattered in the AWS Console and it is very complicated to track down the AWS services you are using only by looking in there.&lt;/p&gt;

&lt;p&gt;The problem is that from a developer's point of view, you don't have a very-much-needed, app-centric view of the serverless services you are using to compose your application. Of course, AWS Console is not the answer, but pointing the developer to lengthy AWS SAM or CloudFormation YAML files is also NOT the answer. That's not the right developer experience.&lt;/p&gt;

&lt;p&gt;In a sense, new developer cloud tech such as Terraform and AWS CDK partially alleviated this problem. With Infrastructure as Code scripts, you can now have a dedicated repo of source code that defines and composes your infrastructure. Now, you can see all the services you are using just by looking at the IaC project structure in VS Code! That's a secondary code repo, separated from the main application business code repo, and that's okay. The IaC code repository is just for application composition code, not business logic, and it's good to have them separated. One could argue that the new &lt;a href="https://aws.amazon.com/application-composer/" rel="noopener noreferrer"&gt;AWS Application Composer&lt;/a&gt; service introduced at this year's AWS re:Invent visually solves this problem. I have feelings about this service generating YAML code, although I like the idea of deploying your UML collaboration diagram as a serverless app!&lt;/p&gt;

&lt;p&gt;So, where is all this heading? What's next after serverless that niche players can help with? It seems that the answer pivots around a better developer experience to build serverless apps, and here's an idea that &lt;strong&gt;new&lt;/strong&gt; cloud providers are introducing: Why do you even care about what serverless services you are using to compose your app? What if you let the cloud platform decide what is the best infrastructure needed for your application based on its code?&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://www.readysetcloud.io/blog/allen.helton/first-impression-of-infrastructure-from-code/" rel="noopener noreferrer"&gt;Infrastructure FROM Code&lt;/a&gt;. I see an evolution here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure and code&lt;/strong&gt;: This is traditional DevOps and IaaS, where operations teams write deployment scripts in chef, puppet, or custom tech to connect users with the infrastructure necessary to run the app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure as code&lt;/strong&gt;: This is where where developers can write their own Terraform and AWS CDK scripts to compose the infrastructure necessary for their apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure from code&lt;/strong&gt;: This is where cloud providers transparently provision the infrastructure resources needed to run your applications, so development nor operations teams need to care about it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Infrastructure From Code
&lt;/h2&gt;

&lt;p&gt;First of all, let me clarify something. In my opinion, those niche players betting on &lt;em&gt;Infrastructure from Code&lt;/em&gt; frameworks qualify as cloud providers. As I said multiple times, you don't need to own a data center and offer your infrastructure and runtimes as a service to be a cloud provider. Instead, evolve and industrialize your services (even if it is pure software) and offer your resources as commodities with sprinkles of self-service, and you also will become a cloud provider.&lt;/p&gt;

&lt;p&gt;Okay, what examples of cloud providers fit this definition and offer Infrastructure from Code features? The answer is many already, with players such as &lt;a href="https://getampt.com/" rel="noopener noreferrer"&gt;Ampt&lt;/a&gt; and &lt;a href="https://dev.to/ivancernja/infrastructure-from-code-not-as-but-from-5dpg"&gt;Shuttle&lt;/a&gt; disrupting the space with purpose-built IfC features and development kits.&lt;/p&gt;

&lt;p&gt;However, I have to reckon that &lt;a href="https://dev.to/peibolsang/how-vercel-is-changing-the-cloud-game-fme"&gt;I have a hard bias toward Vercel for multiple reasons&lt;/a&gt;, the main one being precisely their Infrastructure from Code features designed explicitly for frontend developers building with the Next.js framework. Think about the following potential scenarios if you are building a Next.js app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are hosting the app on your own infrastructure, it is very likely that after you get your UI bundle with all the assets, you have to put it on a &lt;code&gt;nextjs&lt;/code&gt; hot server running inside a container (&lt;a href="https://stackoverflow.com/questions/58112093/how-to-deploy-next-js-9-to-aws-lambda" rel="noopener noreferrer"&gt;or inside an AWS Lambda function if you are brave enough&lt;/a&gt;). In any case, you need to think about the computing services you need, provision them with Terraform or AWS CDK scripts (if you are using AWS), and get your app deployed.&lt;/li&gt;
&lt;li&gt;However, if you are hosting the app on Vercel, you don't need to think about this. Vercel takes care of the bundle splitting to deploy the respective assets on the right piece of infrastructure. And they do this transparently during the build process, so you don't even care what AWS (or other) serverless services they are using under the hood. They could get the static assets to an AWS S3 bucket, the SSR bits to an AWS Lambda function, and the Edge Functions to another server running on the CDN. In fact, that's what they actually do!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the case of Vercel, the Infrastructure from Code features are super-powerful for your Next.js app. Because they own both the framework and the platform, they are in a very good position to offer this kind of added-value service, &lt;a href="https://twitter.com/ascorbic/status/1585218371897167872?s=20&amp;amp;t=psF2xsGXoiu5XBJ1NvAvvw" rel="noopener noreferrer"&gt;while others need to run behind catching up all the time!&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;It's hard to predict where things might go in terms of cloud development, but one thing remains clear to me: there is an opportunity for startups to bet on serverless development experience. This is something that hyperclouds wouldn't do. This is still an unchartered area where we need definitions and techniques, but this is very likely what the future of native cloud development looks like.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Cover photo credit: Alex Kulikov via Unsplash)&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>serverless</category>
      <category>aws</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>What does the cloud look like for software companies?</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Mon, 25 Apr 2022 07:34:35 +0000</pubDate>
      <link>https://dev.to/peibolsang/what-does-the-cloud-look-like-for-software-companies-18g</link>
      <guid>https://dev.to/peibolsang/what-does-the-cloud-look-like-for-software-companies-18g</guid>
      <description>&lt;p&gt;When I hear software companies are &lt;em&gt;transitioning to the cloud&lt;/em&gt;, I generally take it with a pinch of salt because I am not sure if they know what they mean. But, what do they really mean?&lt;/p&gt;

&lt;p&gt;This is a rough, unpolished thought but I think we should put more emphasis on distinguishing between &lt;strong&gt;transitioning to the cloud&lt;/strong&gt; vs &lt;strong&gt;becoming the cloud&lt;/strong&gt;. In other words, we shouldn't mistake the &lt;em&gt;cloudifification&lt;/em&gt; of the software with the &lt;em&gt;evolution&lt;/em&gt; of the software towards the services economy. &lt;/p&gt;

&lt;p&gt;Let me be more specific.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transitioning to the cloud vs. becoming the cloud
&lt;/h2&gt;

&lt;p&gt;On the one hand, when a software company &lt;strong&gt;transitions to the cloud&lt;/strong&gt; it typically means they are taking their existing software products and moving them to a fancier data center (i.e. "the cloud"). What motivates this change for software providers? In my experience, this is typically a reactive move after their customers have moved all their stuff to the cloud. Operating on new cloud infrastructure, these customers will ask software providers for mechanisms to integrate the software with other infrastructure components on the new cloud platform. The answer is then to lift and shift the software onto AWS EC2 instances so it can integrate better with the customer's AWS S3 buckets.&lt;/p&gt;

&lt;p&gt;While this transition changes the delivery model and ownership of the software (i.e., it is now delivered through the internet) on many occasions there is a tendency to leave it untouched without rethinking how the customers will use it in this new world. Typically, these are enterprise software companies that still allow customers to work with their software in the same way they did before the transition to cloud. Now, it just happens that they are operating in a more reliable, secure, and scalable environment (i.e., a fancier data center). This way, customers can still do whatever customizations they used to apply without any restrictions. In order to give these customers full control as they used to have, these software companies end up building complex control planes and integrations that mimic the underlying cloud platform consoles in an attempt to enable full control to the customers.&lt;/p&gt;

&lt;p&gt;On the other hand, when a software company &lt;strong&gt;becomes the cloud&lt;/strong&gt; they not only move their software to the cloud, but they also rethink their product strategy by offering many of the software capabilities in a self-service manner. In other words, they move forward the industrialization line towards the services economy. We've got 2 options here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Option 1: software companies create guidelines and constraints to allow users to customize the software in a very specific and controlled way. This is how the gurantee evergeen updates to the &lt;em&gt;untouchable&lt;/em&gt; parts. For that, they create platform abstractions and tools for these users to create extensions or even entirely new applications within the boundaries of the platform they have been offered. This is Platform as a Service or PaaS, where the customers own the data and the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Option 2: software companies eliminate all customization possibilities and rethink how their software is offered as a service, allowing the users to introduce only certain and restricted configurations for their use cases. This is Software as a Service or SaaS, where the customers only own the data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lmEB3ic4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xyyoz6yv7ub8am3evssu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lmEB3ic4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xyyoz6yv7ub8am3evssu.png" alt="Image description" width="880" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The evolution of the enterprise software
&lt;/h2&gt;

&lt;p&gt;I think a safe strategy in the current legacy enterprise software industry (i.e., B2B) is to &lt;strong&gt;become the cloud&lt;/strong&gt; and offer both &lt;strong&gt;Build and Buy&lt;/strong&gt; options to the their customers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;So-called &lt;em&gt;core&lt;/em&gt; legacy systems could be offered through SaaS with self-service configuration capabilities to final customers. These applications typically are important to sustain the business ... but they are also the cost of doing business. For example, the cost of having customers is managing relationships and offers (e.g., with a CRM such as Salesforce) and the cost of shipping goods is managing a supply chain (e.g, with an ERP such as SAP Ariba). Typically companies do not differentiate between each other thanks to these types of systems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Building the so-called &lt;em&gt;digital experience&lt;/em&gt; applications could be offered through PaaS with constrained customizations and developer tools. This way, consumer companies have full control on how they build these types of applications, while the software provider does not leave them alone, giving them platforms to build users experiences with efficacy. Yes, these are the applications that companies want to build because they are differentiating and help them achieve competitive advantages. For example, insurance carriers differentiate between each other for the Quote and Buy experience they offer to final consumers, so they can capture more business. That's why the want to build them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is the cloud anyway?
&lt;/h2&gt;

&lt;p&gt;I know what you might be thinking: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"But, wait a minute Pablo, I thought cloud companies are just those that own data centers and offer infrastructure resources as a service, like AWS"&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While this is entirely true, owning a data center and offering infrastructure or runtime services through an HTTP endpoint is not a necessary precondition for any tech company to become a &lt;strong&gt;cloud company&lt;/strong&gt;. Let's pause for a moment and think about what cloud services actually are. The term has been so used and abused that it makes people think that cloud services are just those offered by AWS, Microsoft, or Google. However, the term cloud services capture the industrialization of the technology and practices of any business to offer their capabilities as commodities, moving from competing in the product space to competing in the services space. Top that with sprinkles of self-service and evergreen updates and you'll become a true cloud company!&lt;/p&gt;

&lt;p&gt;That's what cloud services are all about, and that's why software companies of all kinds can become cloud companies too. &lt;/p&gt;

&lt;p&gt;That's &lt;strong&gt;the cloud&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S38-VJUI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tsbb6guygh8jrgg3afrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S38-VJUI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tsbb6guygh8jrgg3afrr.png" alt="Image description" width="880" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://twitter.com/peibolsang"&gt;Twitter&lt;/a&gt; to keep the conversation going!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Cover photo credits: Javier Allegue Barros via Unsplash)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>software</category>
      <category>platform</category>
      <category>cloud</category>
    </item>
    <item>
      <title>A software engineering analogy nobody asked for</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Sun, 03 Apr 2022 19:16:19 +0000</pubDate>
      <link>https://dev.to/peibolsang/a-software-engineering-analogy-nobody-asked-for-5ehc</link>
      <guid>https://dev.to/peibolsang/a-software-engineering-analogy-nobody-asked-for-5ehc</guid>
      <description>&lt;h2&gt;
  
  
  Seeking analogies
&lt;/h2&gt;

&lt;p&gt;Most of us have heard many analogies comparing software engineering to other engineering practices in the physical world, such as civil engineering or car manufacturing. While seeking metaphors like these is absolutely normal due to the inherent abstract (an intangible) nature of building software, many fail to make a genuine and equivalent comparison.&lt;/p&gt;

&lt;p&gt;Let me explain.&lt;/p&gt;

&lt;p&gt;Comparing building software to make cars is very tempting since there seem to be some similarities, to the point that we have even spun up &lt;em&gt;software factories&lt;/em&gt; in the past. These so-called factories were based on the principles of Lean Manufacturing and the hyper-efficient and highly-automated assembly lines. There is a problem though: we don't make cars. A Toyota Prius has nothing in common with Elastic Search.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation in car manufacturing
&lt;/h2&gt;

&lt;p&gt;Why is it so tempting? Let me put it this way. In manufacturing, there are two clear and well-separated processes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Design Phase&lt;/strong&gt;: You design that new car model that all your customers dream about. You capture market needs and then put your creativity together to develop a model that can be handed over to engineers to build and deliver.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Construction Phase&lt;/strong&gt;: You build that one car model that has been designed, typically through a highly-automated and hyper-efficient assembly line.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you noticed something already? That's right. In the car manufacturing industry, you &lt;strong&gt;automate&lt;/strong&gt; the construction phase but never the design phase. I may be wrong, but I don't think that designing new car models can be automated in the same way they are produced. Don't mistake using software to &lt;strong&gt;assist&lt;/strong&gt; the design phase (e.g., CAD) with software to &lt;strong&gt;automate&lt;/strong&gt; the generation of new designs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Automation in software
&lt;/h2&gt;

&lt;p&gt;For building software, these two types of phases also make sense. But not in the way many people think. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Design Phase (or Inner Loop)&lt;/strong&gt;: You design that new piece of software that your customers (think they) want. However, the tricky part is that in software, this phase includes making technical designs &lt;strong&gt;and writing code&lt;/strong&gt;. Exactly, writing code belongs to the design phase. Writing code is designing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Construction Phase (or Outer Loop)&lt;/strong&gt;: You make digital copies of that one software you have designed and ship it to your users. This is the &lt;strong&gt;build and deploy&lt;/strong&gt; part of crafting software.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhvk7f6n0e9hv3gk10l9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhvk7f6n0e9hv3gk10l9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here is the problem of comparing manufacturing cars with building software. There is a misbelief that because cars are produced in hyper-automated assembly lines, building software can be automated in the same way. &lt;/p&gt;

&lt;p&gt;And that's wrong. In software development, when you automate something, what you are really doing is &lt;strong&gt;constraining&lt;/strong&gt; that thing with automation. And you can only constrain a problem that is well known with a high degree of certainty.&lt;/p&gt;

&lt;p&gt;Automation in software engineering must be applied to the build and deploy phase (i.e., the construction phase) and never to the coding phase (i.e., the design phase). Let's think about this as if it was a physics problem: data has mass, computing consumes energy, and the network takes time.&lt;br&gt;
Then, you want to minimize all those variables during your creative work so it runs smoothly while you don't mind to maximize them to make digital copies of that work.&lt;/p&gt;

&lt;p&gt;And this is where I believe that designing cars and building software is equivalent: you come up with a model that later you can copy multiple times and ship it to your customers. Again, in software, writing code is designing. That's why movements such as &lt;strong&gt;Extreme Programming&lt;/strong&gt; promote the idea of &lt;em&gt;designing every day&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Moreover, in software engineering bringing these two &lt;em&gt;phases&lt;/em&gt; as closely as possible with short feedback loops during multiple iterations makes it really different from other types of engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This idea has a corollary.&lt;/p&gt;

&lt;p&gt;Bringing the world's best software engineers does not guarantee that you will build a successful software product that the customers will love to use. You need something else. There is a creative part that can't be neglected. In this way, building software is closer to making a movie than making a car. However, bringing the world's best software engineers will guarantee that this piece of software is built and shipped with efficacy to these customers.&lt;/p&gt;

&lt;p&gt;That's what I think. &lt;a href="https://twitter.com/peibolsang" rel="noopener noreferrer"&gt;Follow me on Twitter&lt;/a&gt; for more stupid rants like this! &lt;/p&gt;

&lt;p&gt;(Cover photo by Hal Gatewood via Unsplash)&lt;/p&gt;

</description>
      <category>programming</category>
      <category>devops</category>
      <category>design</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Modern Web Development with the Modern Cloud</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Wed, 09 Mar 2022 15:21:00 +0000</pubDate>
      <link>https://dev.to/peibolsang/modern-web-frameworks-in-the-modern-cloud-2je0</link>
      <guid>https://dev.to/peibolsang/modern-web-frameworks-in-the-modern-cloud-2je0</guid>
      <description>&lt;h2&gt;
  
  
  Different rendering options
&lt;/h2&gt;

&lt;p&gt;It appears to me that making architectural decisions for Web development is more complicated than ever due to the emergence of frameworks that bake in client/server tradeoffs. Yes, I am thinking of &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; or &lt;a href="https://remix.run/"&gt;Remix&lt;/a&gt;, which offer different rendering options for different use cases. In any case, there is a lot of information out there to help Web developers make informed decisions.&lt;/p&gt;

&lt;p&gt;Typically, Web developers solve these tradeoffs and pick one rendering method or another driven by a combination of data and user experience requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Static Site Generation (SSG)&lt;/strong&gt;: Pages of your Web App / Web Site are generated at build time. It helps build sites when data is not changed or updated frequently, such as information portals or news sites. Frameworks like Next.js support features such as &lt;a href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration"&gt;Incremental Static Regeneration&lt;/a&gt; which means that the static site is regenerated &lt;strong&gt;on the server&lt;/strong&gt; automatically based on a schedule configured by developers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt;: Content of your Web App / Web Site is generated dynamically on a request basis. This rendering solution is most appropriate for data-intensive scenarios where content is updated very frequently, it is very large, access latency is critical, or complex processing and transformation is needed before returning the response to the client.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Side Rendering (CSR)&lt;/strong&gt;: The data displayed on your Web App / Web Site is served through an HTTP API and rendered by the client on the browser. To improve the performance time at the client device, this data must be lightweight and ready to be consumed without further processing. This approach can help for those cases where user interactions and state management of the user interface need to happen as close to the user as possible to offer a very interactive and reactive user experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, modern deployment options have additional non-functional requirements (NFRs). I am talking about NFRs such as an extra twist in performance, cost implications, and environmental impact. These are things that nowadays Web Developers need to consider when making these architectural decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The battle at the server-side
&lt;/h2&gt;

&lt;p&gt;I believe the discussion and debate around what rendering mechanism is better is conceptually wrong. It may lead you to pick up the wrong framework after all!&lt;/p&gt;

&lt;p&gt;The actual tradeoffs and the real discussion should be around architectural patterns such as JAMstack (i.e., no server-side logic) vs Fullstack (i.e., server-side logic). When you put the focus on the architectural style and not the rendering mechanism, you'll see it more clearly as you will look at the problem from a more accurate prism. At the end of the day, you can do SSR with JAMstack but it just happens at build time! Also, you can do SSG with Fullstack if you play with the &lt;code&gt;stale-while-revalidate&lt;/code&gt; cache header like Remix does.&lt;/p&gt;

&lt;p&gt;Why are Web development teams shifting to the server side again? The answer is because of the commoditization of infrastructure and &lt;strong&gt;serverless&lt;/strong&gt;. It is now easier than ever to have backend computing for your Web applications and sites.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"&lt;em&gt;Higher-order systems create new sources of value&lt;/em&gt;" - Simon Wardley&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We now count on an extensive catalog of managed cloud services and pure serverless primitives. There is a battle in this server-side space between second-tier cloud platforms such as Vercel or Netlify (they don't own Datacenters) and first-tier cloud ones such as Cloudflare and AWS (they own Datacenters). They all compete with each other to offer the best Web developer experience and optimize those new NFRs. &lt;/p&gt;

&lt;p&gt;Especially for first-tier cloud platform, this battle is making innovations spring at a pace we have never been before, especially with the emergence of &lt;strong&gt;Edge Computing&lt;/strong&gt; solutions.&lt;/p&gt;

&lt;p&gt;JAMstack was introduced as a &lt;em&gt;workaround&lt;/em&gt; under certain infrastructural assumptions, advocating for the separation of server-side stuff from pure Web development for performance and UX reasons. The world has changed, and Edge Computing is breaking those initial assumptions!&lt;/p&gt;

&lt;p&gt;I mean, you don't need full round trips to the cloud region to obtain data. You can now serve it from the CDN, or even run pieces of logic on the edge. That gives you speeds and UX for dynamic Web Apps that are similar to static sites.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/peibolsang/the-future-of-cloud-computing-is-developer-experience-g0p"&gt;As I wrote in the past&lt;/a&gt;, computing at the edge is not about CDNs and caches anymore; this is something else. We are now talking about moving part of our applications and services to an edge location. An edge location is where cloud providers cache content so that it can be very quickly accessed by local referrers. It also allows local access to the cloud platform's network backbone avoiding the public internet between the edge location and the regional datacenter from where content originates.&lt;/p&gt;

&lt;p&gt;At the edge, actual client requests and application logic can be processed and executed without the need to send that request to a service running on the origin cloud region. Of course, this approach still qualifies as serverless because you don't need to provision or manage any type of runtime. Additionally, this approach comes with further benefits, such as global distribution and automatic multi-region access for your applications out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edge Computing use cases
&lt;/h2&gt;

&lt;p&gt;Okay, then, how does edge computing help Web development? In my opinion, it can make it better, faster, and cheaper with solutions that help and support the Javascript development community. Solutions such as &lt;a href="https://workers.cloudflare.com/"&gt;Cloudflare Workers&lt;/a&gt; (or &lt;a href="https://developers.cloudflare.com/pages/platform/functions"&gt;Cloudflare Page Functions&lt;/a&gt;) are very confortable for Web developers as they offer the same native Javascript APIs that developers are used to work with in the browser. It's a very natural ecosystem for them.&lt;/p&gt;

&lt;p&gt;In its current form, I would choose Edge Computing services only as an add-on layer on top of my server-side components running at the cloud origin for very concrete use cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data Filtering&lt;/strong&gt;: Filter data coming from the application components before sending a response to the client. This can be done based on user-specific criteria such as location or device type. The goal is to avoid data processing and filtering as much as possible at the browser, so it can receive ready-to-render data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateful Requests&lt;/strong&gt;: Combined with lightweight storage at the edge (e.g., Key-Value stores), we could handle sophisticated states on edge on top of the application running on a serverless environment. And we could do it without firing full round trips to the cloud origin region. This would allow Web developers to build session-based online collaboration tools (e.g., Miro dashboard) running on serverless computing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization&lt;/strong&gt;: Apply Role Based Access Control rules to UI components returned to the client. Imagine you are including an Admin section in your UI which options are affected by the user's role. Filtering those UI options at the edge would be a very cost-effective and high-performant solution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cyber-protection&lt;/strong&gt;: Use native cybersecurity features and APIs at the CDN to identify networking patterns such as bot detection and apply URL redirects to avoid exposing the application code running at cloud region to malicious agents. Also, I've seen edge functions used to prevent &lt;em&gt;clickjacking&lt;/em&gt; or &lt;em&gt;XSS&lt;/em&gt; attacks by &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-security-headers.html"&gt;adding security headers to the response&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Remember that edge computing providers own cache datacenters all over the world, so I am sure there is one close to your location right now. This allow them implement powerful caching mechanisms to improve TTFB for static content (HTML, CSS, Javascript bundles) and other techniques such as image resizing optimization based on user devices. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;These use cases can be game-changing especially for Javascript developers building Web applications. Solutions like Cloudflare Workers are based on &lt;a href="https://v8.dev/"&gt;Google's V8 engine&lt;/a&gt; allowing response times for client requests under 50ms (i.e., full round-trip, not just internal execution time). Then, as described above, the main logic for the server-side components would run entirely on the cloud region, with a preference for serverless components. But who knows, maybe edge computing evolves to the point where we can run larger pieces of business logic closer to the user location.&lt;/p&gt;

&lt;p&gt;I am getting my hands dirty with a few of Cloudflare's solutions right now, so in my next post I will cover in detail a few of their most compelling edge computing services. Follow me on &lt;a href="https://twitter.com/peibolsang"&gt;Twitter&lt;/a&gt; to keep the conversation going!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Cover photo credits: Alan Tang via Unsplash)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cloud</category>
      <category>javascript</category>
      <category>serverless</category>
    </item>
    <item>
      <title>How Edge Computing can make the Web better</title>
      <dc:creator>Pablo Bermejo</dc:creator>
      <pubDate>Sun, 06 Mar 2022 17:30:24 +0000</pubDate>
      <link>https://dev.to/peibolsang/how-edge-computing-can-make-the-web-better-6b2</link>
      <guid>https://dev.to/peibolsang/how-edge-computing-can-make-the-web-better-6b2</guid>
      <description>&lt;h2&gt;
  
  
  Different rendering options
&lt;/h2&gt;

&lt;p&gt;It appears to me that making architectural decisions for Web development is more complicated than ever due to the emergence of frameworks that bake in client/server tradeoffs. Yes, I am thinking of &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; or &lt;a href="https://remix.run/"&gt;Remix&lt;/a&gt;, which offer different rendering options for different use cases. In any case, there is a lot of information out there to help Web developers make informed decisions.&lt;/p&gt;

&lt;p&gt;Typically, Web developers solve these tradeoffs and pick one rendering method or another driven by a combination of data and user experience requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Static Site Generation (SSG)&lt;/strong&gt;: Pages of your Web App / Web Site are generated at build time. It helps build sites when data is not changed or updated frequently, such as information portals or news sites. Frameworks like Next.js support features such as &lt;a href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration"&gt;Incremental Static Regeneration&lt;/a&gt; which means that the static site is regenerated &lt;strong&gt;on the server&lt;/strong&gt; automatically based on a schedule configured by developers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt;: Content of your Web App / Web Site is generated dynamically on a request basis. This rendering solution is most appropriate for data-intensive scenarios where content is updated very frequently, it is very large, access latency is critical, or complex processing and transformation is needed before returning the response to the client.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Side Rendering (CSR)&lt;/strong&gt;: The data displayed on your Web App / Web Site is served through an HTTP API and rendered by the client on the browser. To improve the performance time at the client device, this data must be lightweight and ready to be consumed without further processing. This approach can help for those cases where user interactions and state management of the user interface need to happen as close to the user as possible to offer a very interactive and reactive user experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, modern deployment options have additional non-functional requirements (NFRs). I am talking about NFRs such as an extra twist in performance, cost implications, and environmental impact. These are things that nowadays Web Developers need to consider when making these architectural decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The battle at the server-side
&lt;/h2&gt;

&lt;p&gt;We now count on an extensive catalog of managed cloud services and pure serverless primitives. There is a battle in this server-side space between second-tier cloud platforms such as Vercel or Netlify (they don't own Datacenters) and first-tier cloud ones such as Cloudflare and AWS (they own Datacenters). They all compete with each other to offer the best Web developer experience and optimize those new NFRs. &lt;/p&gt;

&lt;p&gt;Especially for first-tier cloud platform, this battle is making innovations spring at a pace we have never been before, especially with the emergence of &lt;strong&gt;Edge Computing&lt;/strong&gt; solutions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/peibolsang/the-future-of-cloud-computing-is-developer-experience-g0p"&gt;As I wrote in the past&lt;/a&gt;, computing at the edge is not about CDNs and caches anymore; this is something else. We are now talking about moving part of our applications and services to an edge location. An edge location is where cloud providers cache content so that it can be very quickly accessed by local referrers. It also allows local access to the cloud platform's network backbone avoiding the public internet between the edge location and the regional datacenter from where content originates.&lt;/p&gt;

&lt;p&gt;At the edge, actual client requests and application logic can be processed and executed without the need to send that request to a service running on the origin cloud region. Of course, this approach still qualifies as serverless because you don't need to provision or manage any type of runtime. Additionally, this approach comes with further benefits, such as global distribution and automatic multi-region access for your applications out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edge Computing use cases
&lt;/h2&gt;

&lt;p&gt;Okay, then, how does edge computing help Web development? In my opinion, it can make it better, faster, and cheaper with solutions that help and support the Javascript development community. Solutions such as &lt;a href="https://workers.cloudflare.com/"&gt;Cloudflare Workers&lt;/a&gt; (or &lt;a href="https://developers.cloudflare.com/pages/platform/functions"&gt;Cloudflare Page Functions&lt;/a&gt;) are very confortable for Web developers as they offer the same native Javascript APIs that developers are used to work with in the browser. It's a very natural ecosystem for them.&lt;/p&gt;

&lt;p&gt;In its current form, I would choose Edge Computing services only as an add-on layer on top of my server-side components running at the cloud origin for very concrete use cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Data Filtering&lt;/strong&gt;: Filter data coming from the application components before sending a response to the client. This can be done based on user-specific criteria such as location or device type. The goal is to avoid data processing and filtering as much as possible at the browser, so it can receive ready-to-render data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateful Requests&lt;/strong&gt;: Combined with lightweight storage at the edge (e.g., Key-Value stores), we could handle sophisticated states on edge on top of the application running on a serverless environment. And we could do it without firing full round trips to the cloud origin region. This would allow Web developers to build session-based online collaboration tools (e.g., Miro dashboard) running on serverless computing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization&lt;/strong&gt;: Apply Role Based Access Control rules to UI components returned to the client. Imagine you are including an Admin section in your UI which options are affected by the user's role. Filtering those UI options at the edge would be a very cost-effective and high-performant solution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cyber-protection&lt;/strong&gt;: Use native cybersecurity features and APIs at the CDN to identify networking patterns such as bot detection and apply URL redirects to avoid exposing the application code running at cloud region to malicious agents. Also, I've seen edge functions used to prevent &lt;em&gt;clickjacking&lt;/em&gt; or &lt;em&gt;XSS&lt;/em&gt; attacks by &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-security-headers.html"&gt;adding security headers to the response&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Remember that edge computing providers own cache datacenters all over the world, so I am sure there is one close to your location right now. This allow them implement powerful caching mechanisms to improve TTFB for static content (HTML, CSS, Javascript bundles) and other techniques such as image resizing optimization based on user devices. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;These use cases can be game-changing especially for Javascript developers building Web applications. Solutions like Cloudflare Workers are based on &lt;a href="https://v8.dev/"&gt;Google's V8 engine&lt;/a&gt; allowing response times for client requests under 50ms (i.e., full round-trip, not just internal execution time). Then, as described above, the main logic for the server-side components would run entirely on the cloud region, with a preference for serverless components. But who knows, maybe edge computing evolves to the point where we can run larger pieces of business logic closer to the user location.&lt;/p&gt;

&lt;p&gt;I am getting my hands dirty with a few of Cloudflare's solutions right now, so in my next post I will cover in detail a few of their most compelling edge computing services. Follow me on &lt;a href="https://twitter.com/peibolsang"&gt;Twitter&lt;/a&gt; to keep the conversation going!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Cover photo credits: Alan Tang via Unsplash)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cloud</category>
      <category>edge</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
