Comparing JAMstack and Rails
8 min read | March 20 2021
One of my fellow Netlify Pilots, Aaron recently proposed this question in The Forums:
There is often talk of Statics sites and Dynamic sites. The difference seems simple but I feel with JAMStack, prerendering initial load with hydration etc, the lines become blurred?
I want to ask everyone, what can’t JAMStack do? In what situation would it not work? As far as I can tell I’ve made CRUD applications, data driven interactive applications too. With sites such as blogs it tends to be that most will rebuild when content changes, invalidate cache and immediately go live, but you can still pull data from api’s and trigger CRUD actions on databases via apis.
I’ve found that I end up writing more apis like wrappers around other services and they are naturally more reusable.
Is there anything I am missing that a truly dynamic site handles way better or something that JAMStack can simply just not achieve?
And ultimately, that’s a fantastic question. What are the ‘limits’ of JAMstack? What can’t JAMstack accomplish? This got me down a thought rabbit-hole and had me actively comparing JAMstack to Rails pretty deepy… although Rails is a specific framework and JAMstack is just a paradigm, still. Here’s what I wrote back:
tl;dr: JAMstack’s benefits shine most for web sites rather than web apps
Contrast that with a web-app. (Yes I know this is a definition subject to much internet-scrutiny) A web-app is an application — something you interact with heavily in both directions. You issue commands to the application and it does things, it gives you feedback and tells you information. This is all very vague but the key signature that differentiates a web site from a web app is the level of two-way interactivity that occurs.
Netlify itself actually hosts a great example of this contrast. Go look at Netlify.com (the public marketing website) — click around on some pages and read some stuff.. then click around to other pages and read more stuff 😜 pretty much everything on Netlify.com is textual/image content made to be consumed by you and me. That’s one-way interactivity. They write stuff on the site and we read it. Is there a way to ‘interact’ with the site? Sorta — this page https://www.netlify.com/enterprise/contact/ has a nice contact form that allows you to interact with the site in the other direction (us sending data back to Netlify) but that’s about it for Netlify.com (and, for what it’s worth, that form is actually a Hubspot embedded form.. so not really “part of the site” anyway).
Now instead go to app.netlify.com — the admin interface for all of your Netlify sites. There’s data there for you to see; tons of it! Each site’s build status, your bandwidth usage, build minutes used, domain setup, etc. etc., basically all of the features of Netlify. So that covers the “one-way” interactivity in the sense that Netlify is telling us data. But look how much interactivity there is in the other direction: I can add new sites, kick off builds, control site settings, heck I can log in — there’s a whole user system in place and all the content is customized per user (I can’t see your sites! 😛), etc. The premise I’m making here is that there’s a ton of interactivity in both directions. app.netlify.com (aptly named) is a web-app. Not a web-site. In this particular case, it’s an app for managing our Netlify sites, but nonetheless, an app.
SO, I say all of that to say my hot take: the benefits of a JAMstack site are maximized by web-sites but shrink quite a bit when using JAMstack to build web-apps. But why? Because of static rendering. When we think about all of the two-way interactivity involved in a web-app, almost always that involves user-specific content. It’s the reason I can’t see your sites when I log into app.netlify.com and you can’t see mine, even if you tried to go to
https://app.netlify.com/teams/jon-sully/. The content that ultimately renders in my view is different than yours: the number of sites I have and their names, the settings for each of them, my team’s name, the domains I use — literally all of the interactivity sections (in either direction) that I described earlier will be different between the two of us. That means that none of that content can be rendered statically at build-time — anything rendered statically at build time will be available just the same to everyone. In the case of app.netlify.com the static content — the HTML rendered at build time — is mostly just the basic design layout and header text. Everyone’s going to see this same box shape with these same
h2 buttons and links:
On the other hand, using JAMstack for web-sites is unbeatable. Traditional server-based frameworks can leverage caching tools and mechanisms to achieve close-to-JAMstack-level results but not without a lot more complexity and knowledge. If your site is mostly statically-rendered (build-time) content, then packing that down to plain HTML files and distributing them across a global CDN is hard to beat. There’s just no denying it. Things that can be rendered at build-time should be.
Different projects just have different needs.
And, before closing out, I should mention that there are a ton of shades of grey here too. Is an eCommerce site a web-site or a web-app? I’ll let you decide 😅 but the point is that many web-sites can be better off with JAMstack over a traditional server-render approach even if they have some per-user pieces of content / components (e.g. all of your products can be build-time rendered but your shopping cart and order history better be per-user). The balance lies in how much of your project’s content is static vs. user-driven. Understanding that balance will lead you to the right tool for the job. 💯
I’m also not going to get into the sort-of-server-rendered approach using serverless functions instead of an actual server framework — more shades of gray there. Looking at you, NextJS!
Hope that provides some insight!
There you have it!
When figuring out the right tool for the project just remember, the two primary factors are how much of the content is static (not changing per-user) and the required latency between the content updating and becoming available publicly.
Oh! And if you ever wonder how fast the server-side approach can be with just a few good caching policies, head over to Dev.to. Ignoring the article contents, just experience how fast the whole site runs. It’s Rails 😜