I recently moderated a panel at Netlify’s virtual Jamstack Conf that included Netlify CEO Matt Biilman and Automattic founder Matt Mullenweg. The whole thing was built up — at least to some — as a “Jamstack vs. WordPress” showdown.
I have lots of thoughts of my own on this and think I’m more useful as a pundit than a moderator. This is one of my favorite conversations in tech right now! So allow me to blog.
Disclosure: both Automattic and Netlify are active sponsors of this site. I have production sites that use both, and honestly, I’m a fan of both, which is an overarching point I’ll try to make. I also happen to be writing and publishing this on a WordPress site.
- Richard MacManus published “WordPress Co-Founder Matt Mullenweg Is Not a Fan of JAMstack” with quotes from an email conversation between them a line from Matt saying, “JAMstack is a regression for the vast majority of the people adopting it.”
- Matt Biilmann published a response “On Mullenweg and the Jamstack – Regression or Future?” with a whole section titled “The end of the WordPress era.”
- People chimed in along the way. Netlify board member Ohad Eder-Pressman wrote an open letter. Sarah Gooding rounded up some of the activity on WP Tavern (which is owned by Matt Mullenweg). I chimed in as well.
- Matt Mullenweg clarified remarks with some new zingers.
The debate was on October 6th at Jamstack Conf Virtual 2020. There is no public video of it (sorry).
Comparing Jamstack to WordPress is a bit weird. What is comparable is the fact that they are both roads you might travel when building a website. Much of this post will keep that in mind and compare the two that way. Why they aren’t directly comparable is because:
- WordPress is a CMS on the LAMP stack.
Those things are not apples to apples.
If we stick just with the stack for a moment, the comparison would be between:
- Static Hosting + Services
An example of Static + Services is using Netlify for hosting (which is static) and using services to do anything dynamic you need to do. Maybe you use Netlify’s own forms and auth functionality and Hasura for data storage.
On a LAMP stack, you have MySQL to store data in, so you aren’t reaching for an outside service there. You also have PHP available. So with those (in addition to open-source software), you have what you need for auth. It doesn’t mean that you never reach for services; you just do so less often as you have more technology at your fingertips from the server you already have.
Matt B. called the LAMP stack a “monolith.” Matt M. objected to that term and called it an “integrated approach.” I’m not a computer scientist, but I could see this going either way. Here’s Wikipedia:
[…] a monolithic application describes a single-tiered software application in which the user interface and data access code are combined into a single program.
Defined that way, yes, WordPress does appear to be a monolith, and yet the Wikipedia article continues:
[…] a monolithic application describes a software application that is designed without modularity.
Seen that way, appears to disqualify WordPress as a monolith. WordPress’ hook and plugin architecture is modular. 🤷♂️
It would be interesting to hear these two guys dig into the nuance there, but the software is what it is. A self-hosted WordPress site runs on a server with a full stack of technology available to it. It makes sense to ask as much of that server as you can (i.e. integrated). In a Jamstack approach, the server is abstracted from you. Everything else you need to do is split into different services (i.e. not integrated).
The WordPress approach, doesn’t mean that you never reach for outside services. In both stacks, you’d likely use something like Stripe for eCommerce APIs. You might reach for something like Cloudinary for robust media storage and serving. Even WordPress’ Jetpack service (which I use and like) brings a lot of power to a self-hosted WordPress site by behaving like a third-party service and moving things like asset-hosting and search technology off your own servers by moving them over to cloud servers. Both stacks are conglomerations of technologies.
Neither stack is any more “house of cards” or prone than the other. All websites can have that “only as strong as its weakest link” metaphor apply to them. If a WordPress plugin ships a borked version or somehow is corrupted on upload, it may screw up my site until I fix it. If my API keys become invalid for my serverless database, my Jamstack site might be hosed until I fix it. If Stripe is down, I’m not selling any products on any kind of site until they are back up.
WordPress.com has a free plan, and that’s absolutely a place you can build a site. (I have several.) But you don’t really have developer-style access to it until you’re on the business plan at $25 per month. Self-hosted WordPress itself is open-source and free, but you’re not going to find a place to spin up a self-hosted WordPress site for free. It starts cheap and scales up. You need LAMP hosting to run WordPress. Here’s a look around at fairly inexpensive hosting plans:
- A “shared” Bluehost plan starts at $3.95/month.
- The lowest plan on Flywheel is $14/month. (This site is on an upper-level Flywheel plan.)
- Media Temple has WordPress-specific hosting starting at $20/month. (This site was on a high tier Media Temple plan for a long time.)
- Automattic’s Pressable service has a plan starting at $25/month.
There is money involved right off the bat.
Starting free is much more common with Jamstack, then you incur costs at different points. Jamstack being newer, it feels like a market that’s still figuring itself out.
- Vercel is free until you need team members or features like password protected sites. A single password-protected site is $150/month. You can toss basic auth on any server with Apache for no additional cost.
- Netlify is very similar, unlocking features on higher plans, and offering ala-carte per-site features, like analytics ($9/month) and auth (5,000 active users is $99/month).
- AWS Amplify starts free, but like everything on AWS, your usage is metered on lots of levels, like build minutes, storage, and bandwidth. They have an example calculation of a web app has 10,000 daily active users and is updated two times per month, which costs $65.98/month.
- Azure Static Web Apps hasn’t released pricing yet, but will almost certainly have a free tier or free usage or some kind.
All of this is a good reminder that Netlify isn’t the only one in the Jamstack game. Jamstack just means static hosting plus services.
You can’t make blanket statements like Jamstack is cheaper. It’s far too dependent on the site’s usage and needs. With high usage and a bunch of premium services, Jamstack (much like Serverless in general) can get super expensive. Jamstack says their enterprise pricing starts at $3,000/month, and while you get things like auth, forms, and media handling, you don’t get a CMS or any data storage, that is likely to kick you up much higher.
While this WordPress site isn’t enterprise, I can tell you it requires a server in the vicinity of a $1,000/month, and that assumes Cloudflare is in front of it to help reduce bandwidth directly to the host and Jetpack handling things like media hosting and search functionality. Mailchimp sends our newsletter. Wufoo powers our forms. We also have paid plugins, like Advanced Custom Fields Pro and a few WooCommerce add-ons. That’s not all of it. It’s probably a few thousand per month, all told. This isn’t unique to any integrated approach, but helps illustrate that the cost of a WordPress site can be quite high as well. They don’t publish prices (a common enterprise tactic), but Automattic’s own WordPress VIP hosting service surely starts at mid-4-figures before you start adding third-party stuff.
Bottom line: there is no sea change in pricing happening here.
80% of web performance is a front-end concern.
That’s a true story, but it’s also built on the foundation of the server (accounting for the first 20%). The speediest front-end in the world doesn’t feel speedy at all if the first request back from the server takes multiple seconds. You’ve gotta make sure that first request is smoking fast if you want a fast site.
You know what’s super fast? Global CDNs serving static files. That’s what you want to make happen on any website, regardless of the stack. While that’s the foundation of Jamstack (static CDN-backed hosting), it doesn’t mean WordPress can’t do it.
You take an
index.html file with static content, put that on Netlify, and it’s gonna be smoking fast. Maybe your static site generator makes that file (which, it’s worth pointing out, could very well get content from WordPress). There is something very nice about the robustness and steady foundation of that.
By default, WordPress isn’t making static files that are cachable on a global CDN. WordPress responds to requests from a single origin, runs PHP, which asks the database for stuff, before a response is assembled, and then, finally, the page is returned. That can be pretty fast, but it’s far less sturdy than a static file on a global CDN and it’s far easier to overwhelm with requests.
WordPress hosts know this, and they try to solve the problem at the hosting level. Just look at WP Engine’s approach. Without you doing anything, they use a page cache so that the site can essentially return a static asset rather than needing to run PHP or hit a database. They employ all sorts of other caching as well, including partnering with Cloudflare to do the best possible caching. As I’m writing this, my shoptalkshow.com site literally went down. I wrote to the host, Flywheel, to see what was up. Turns out that when I went in there to turn on a staging site, I flipped a wrong switch and turned off their caching. The site couldn’t handle the traffic and just died. Flipping the caching switch back on instantly solved it. I didn’t have Cloudflare in front of the site, but I should have.
Cloudflare is part of the magic sauce of making WordPress fast. Just putting it in front of your self-hosted WordPress site is going to do a ton of work in making it fast and reliable. One of the missing pieces has been great caching of the HTML itself, which they literally dealt with this month and now that can be cached as well. There is kind of a funny irony in that caching WordPress means caching requests as static HTML and static assets, and serving them from a global CDN, which is essentially what Jamstack is at the end of the day.
Matt M. mentioned that WordPress.com employs global CDNs that kick in at certain levels of traffic. I’m not sure if that’s Cloudflare or not, but I wouldn’t doubt it.
With Cloudflare in front of a WordPress site, I see the same first-response numbers as I do on Netlify sites without Cloudflare (because the do not recommend using Cloudflare in front of Netlify-hosted sites). That’s mid-2-digit millisecond numbers, which is very, very good.
From that foundation, any discussion about performance becomes front-end specific. Front-end tactics for speed are the same no matter what the server, hosting, or CMS situation is on the back end.
There are far more stories about WordPress sites getting hacked than Jamstack sites. But is it fair to say that WordPress is less secure? WordPress is going on a couple of decades of history and has a couple orders of magnitude more sites built on it than Jamstack does. Security aside, you’re going to get more stories from WordPress with those numbers.
Matt M brought up that whitehouse.gov is on WordPress, which is obviously a site that needs the highest levels of security. It’s not that WordPress itself is insecure software. It’s what you do with it. Do you have insecure passwords? That’s insecure no matter what platform you’re using. Is the server itself insecure via file permissions or access levels? That’s not exactly the software’s fault, but you may be in that position because of the software. Are you running the latest version of WordPress? Usage is fragmented, at best, and the older the version, the less secure it’s going to be. Tricky.
It may be more interesting to think about security vectors. That is, at what points it is possible to get hacked. If you have a static file sitting on static hosting, I think it’s safe to say there are fairly few attack vectors. But still, there are some:
- Your hosting account could be hacked
- Your Git repo could be hacked
- Your Cloudflare account could be hacked
- Your domain name could be stolen (it happens)
That’s all true of a WordPress site, too, only there are additional attack vectors like:
- Server-side code: XSS, bad plugins, remote execution, etc.
- Database vulnerabilities
- Running an older, outdated version of WordPress
- The login system is right on the site itself, e.g. bad guys can hammer
I think it’s fair to say there are more attack vectors on a WordPress site, but there are plenty of vectors on any site. The hosting account of any site is a big vector. Anyting that sits in the DNS chain. Any third-party services with logins. Anything with an API key.
Personal experience: this site is on WordPress and has never been hacked, but not for lack of trying. I do feel like I need to think more about security on my WordPress sites than my sites that are only built from static site generators.
Scaling either approach costs money. This WordPress site isn’t massively scaled, but does require some decent scaling up from entry-level server requirements. I serve all traffic through Cloudflare, so a peak at the last 30 days tells me I serve 5 TB of bandwidth a month.
On a Netlify Business plan (600 GB of traffic for $99, then $20 per additional 100 GB) that math works out to $979. Remember when I said this site requires about a server that costs about $1,000/month? I wrote that before I ran these numbers, so I was super close (go me). Jamstack versus WordPress at the scale of this site is pretty neck-and-neck. All hosts are going to charge for bandwidth and have caps with overage charges. Amplify charges $0.15/GB over a 15 GB monthly cap. Flywheel (my WordPress host) charges based on a monthly visitor cap and, over that, it’s $1 per 1000.
The story with WordPress scaling is:
- Use a host that can handle it and that has their own proven caching strategy.
- CDN everything (which usually means putting Cloudflare in front of it).
- Ultimately, you’re going to pay for it.
The story with Jamstack scaling is:
- The host and services are built to scale.
- You have to think about scaling less in terms of can this service handle this, or do I have to move?
- You have to think about scaling more in terms of the fact that every aspect of every service will have pricing you need to keep an eye on.
- Ultimately, you’re going to pay for it.
I’ve had to move around a bit with my WordPress hosting, finding hosts that are in-line with the current needs of the site. Moving a WordPress site is non-trivial, but it’s far easier than moving to another CMS. For example, if you build a Jamstack site on a headless CMS that becomes too pricey, the cost of moving is a bigger job than switching hosts.
I like what Dave Rupert wrote the other day (in a Slack conversation) about comparing performance between the two:
Jamstack: Use whatever thing to build your thing, there’s addons to help you, and use our thing to deploy it out to a CDN so it won’t fall over.
WordPress: Use our thing to build your thing, there’s addons to help you, and you have to use certain hosts to get it to not fall over.
There are other kinds of “scaling” as well. I think of something like number of users. That’s something that all sorts of services use for pricing tiers, which is an understandable metric. But that’s free in WordPress. You can have as many users with as many nuanced permissions as you like. That’s just the CMS, so adding on other services might still charge you by the head. Vercel or Netlify charge you by the head for team accounts. Contentful (a popular headless CMS) starts at $489/month for teams. Even GitHub’s Team tier is $4 per user if you need anything the free account can’t do.
Splitting the Front and Back
This is one of the big things that gets people excited about building with Jamstack. If all of my site’s functionality and content are behind APIs, that frees up the front end to build however it wants to.
- Wanna build an all-static site? OK, hit that API during the build process and do that.
- Wanna build a client-rendered site with React or Vue or whatever? Fine, hit the API client-side.
- Wanna split the middle, pre-rendering some, client-rendering some, and server-rendering some? Cool, it’s an API, you can hit it however you want.
That flexibility is neat on green-field builds, but people are just as excited about theoretical future flexibility. If all functionality and content is API-driven, you’ve entirely split the front and back, meaning you can change either in the future with more flexibility.
- As long as your APIs keep spitting out what the front end expects, you can re-architect the back end without troubling the front end.
- As long as you’re getting the data you need, you can re-architect the front end without troubling the back end.
This kind of split feels “future safe” for sites at a certain size and scale. I can’t quite put my finger on what those scale numbers are, but they are there.
If you’ve ever done any major site re-architecture just to accommodate one side or the other, moving to a system where you’ve split the back end and front surely feels like a smart move.
You can split a WordPress site (we’ll get to that in the “Using Both” section), but by default, WordPress is very much an integrated approach where the front end is built from themes in PHP using very WordPress-specific APIs. Not split at all.
Jamstack has done a good job of heavily prioritizing developer experience (DX). I’ve heard someone call it “a local optimum,” meaning Jamstack is designed around local development (and local developer) experience.
- You’re expected to work locally. You work in your own comfortable (local, fast, customized) development environment.
- Git is a first-class citizen. You push to your production branch (e.g.
main), then your build process runs, and your site is deployed. You even get a preview URL of what the production site will be for every pull request, which is an impressively great feature.
- Use whatever tooling you like. You wanna pre-build a site in Hugo? Go for it. You learned
create-react-appin school? Use that. Wanna experiment with the cool new framework de jour? Have at it. There is a lot of freedom to build however you want, leveraging the fact that you can run a build and deploy whatever folder in your repo you want.
- What you don’t have to do is important, too. You don’t have to deal with HTTPS, you don’t have to deal with caching, you don’t have to worry about file permissions, you don’t have to configure a CDN. Even advanced developers appreciate having to do less.
It’s not that WordPress doesn’t consider developer experience (for example, they have a CLI and it can do helpful things, like scaffold blocks), but the DX doesn’t feel as to-the-core of the project to me.
- Running WordPress locally is tricky, requiring you to run a (X)AMP stack somehow, which involves notoriously finicky third-party software. Thank god for Local by Flywheel. There is some guidance but it doesn’t feel like a priority.
- What should go in Git? To this day, I don’t really know, but I’ve largely settled on the entire
/wp-contentfolder. It feels weird to me there is no guidance or obvious best practices.
- You’re totally on your own for deployment. Even WordPress-specific hosts don’t really nail it here. It’s largely just: here’s your SFTP credentials.
- Even if you have a nice local development and deployment pipeline set up (I’m happy with mine), that doesn’t really help deal with moving the database around, so you’re on own your own there as well.
These are all solvable things, and the WordPress community is so big that you’ll find plenty of information on it, but I think it’s fair to say that WordPress doesn’t have DX down to the core. It’s a little wild-west-y even after all these years.
In fact, I’ve found that because the encouragement of a healthy local development environment is so sidelined, a lot of people just don’t have one at all. This is anecdotal, but now twice is as many years have I found myself involved in other people’s sites that work entirely production-only. That would be one thing if they were very simple sites with largely default behavior, but these have been anything but. They’re very complicated (much more so than this site) involving public user logins, paid memberships and permissions, page builders, custom shortcodes, custom CSS, and just a heck of a lot of moving parts. It scared me to death. I didn’t want to touch anything. They were live-editing PHP to make things work — cowboy coding, as people jokingly call that. One syntax error and the site is hosed, maybe even the very page you’re looking at.
The fact that WordPress powers such a huge swath of the web without particularly good DX is very interesting. There is no Jamstack without DX. It’s an entirely developer-focused thing. With WordPress, there probably isn’t a developer at all on most sites. It’s installed (or just activated, in the case of WordPress.com) and the site owner takes it from there. The site owner is like a developer in that they have lots of power, but perhaps doesn’t write any code at all.
To that end, I’d say WordPress has far more focus on UX than DX, which is a huge part of all this…
CMS and End User UX
WordPress is a damn fine CMS. Even if you don’t like it, there are a hell of a lot of people that do, and the numbers speak for themselves. What you get, when you decide to build a site with WordPress, is a heaping helping of ability to build just about any kind of site you want. It’s unlikely that you’ll have that oops, painted myself into a corner here situation with WordPress.
That’s a big deal. Jenn put her finger on this, noting that the people who use WordPress are a bigger story than a developer’s needs.
WordPress can do an absolute ton of things:
- Blog (or be any type of content-driven CMS-style site)…
- With content previews, which is possible-but-tricky on Jamstack
- Deal with users/permissions…
- Process forms
- Handle plugins to the moon and back
Jamstack can absolutely do all these things too, but now it is Jamstack that is in Wild West territory. When you look at tutorials about how to store data, they often involve explaining how to write individual CRUD functions for a cloud database. That’s down to the metal stuff which can be very powerful, but it’s a far cry from clicking a few buttons, which is what WordPress feels like a lot of the time.
I bet I could probably cobble together a basic Jamstack eCommerce setup with Stripe APIs, which is very cool. But then I’d get nervous when I need to start thinking about inventory management, shipping zones, product variations, and who knows what else that gets complicated in eCommerce-land, making me wish I had something super robust that did it all for me.
Sometimes, we developers are building sites just for us (I do more than my fair share of that), but I’d say developers are mostly building sites for other people. So the most important question is: am I building something that is empowering for the people I’m building it for?
You can pull off a good site manager experience no matter what, but WordPress has surely proven that it delivers in that department without asking terribly much in terms of custom development.
Jamstack has some tricks that I wish I would pull off on WordPress, though. Here’s a big one for me: user-submitted content and updates. I literally have three websites now that benefit from this. A site about conferences, a site about serverless, and an upcoming site about coding fonts. WordPress could have absolutely done a great job at all three of those sites. But, what I really want is for people to be able to update and submit content in a way that I can be like: Yep, looks good, merge. By having gone with a Jamstack approach, the content is in public GitHub repos, and anyone can participate.
I think that’s super great. It doesn’t even necessarily require someone from the public knowing or understanding Git or GitHub, as Netlify CMS has this concept of Open Authoring, which keeps the whole contribution experience in the browser with UI for the editing.
This is a big one that I see brought up a lot. Even Netlify themselves say “There is no Versus.”
Here’s the deal:
- The “A” in “Jam” means APIs. Use APIs to build your site either at build time or client-side.
- WordPress sites, by default, have a REST API (and can have a GraphQL API as well).
- So, hit that API for CMS data on your Jamstack site.
Yep, totally. This works and people do it. I think it’s pretty cool.
- Running a WordPress site somewhere in addition to your Jamstack site means… you’re running a WordPress site in addition to your Jamstack site. There is cost and technical debt to that.
- You often aren’t getting all the value of WordPress. Hitting an API for data might be all you need, but this is a super, very different approach to building a site than building a WordPress theme. You’re getting none of the other value of WordPress. I think of situations like this: you find a neat plugin that adds a fancy Gutenberg block to your site. That’ll “just work” on a WordPress site, but it likely has some special front-end behavior that won’t work if all you’re doing is sucking the HTML from an API. It probably enqueues some additional scripts and styles that you’ll be on your own to figure out how to incorporate where your front-end is hosted, and on your own to maintain updates.
Here’s some players that all have a unique approach to “using both”:
- Frontity: A React framework for WordPress. You run it with a Node server behind it, in addition to your WordPress site. The Node server renders the React into HTML, so you get server-side rendering for all the pages, but you’re also still building an SPA.
- WP2Static: A WordPress plugin that builds a static version of your site and can auto-deploy it when changes are made.
- Strattic: They host the dynamic WordPress site for you (which they refer to as “staging”) and you work with WordPress normally there. Then you choose to deploy, and they also host a static version of your site for you.
- Shifter: Shifter hosts the WordPress site for you. You have two options: 1) run it headlessly (so you’re just hitting the API, REST or GraphQL, for data) or 2) run it statically (so when you have everything in WordPress where you want it, you deploy it, which creates a static version of your site, which they also host, or you can push it elsewhere e.g. Netlify).
There are loads of other ways to integrate both. Here’s our own Geoff and Sarah talking about using WordPress and Jamstack together by using Vue/Nuxt with the REST API and hosting on Netlify.
Just in case this isn’t clear, there are absolutely loads of ways to build websites. If you’re building a Ruby on Rails site, that’s not Jamstack or WordPress. You could argue it’s more like a WordPress site in that it requires a server and you’ll be using that server to do as much as you can. You could also argue it’s more like Jamstack in that, even though it’s not static hosting, it encourages using APIs and piecing together services.
The web is a big place, gang, and this isn’t a zero-sum game. I fully expect WordPress to continue to grow and Jamstack to continue to grow because the web itself is growing. Even if we’re only considering the percentage of market share, I’d still bet that both will grow, pushing whatever else into smaller slices.
I’m not even going to go here. Not because I’m avoiding playing favorites, but because it isn’t necessary. I don’t see developers out there biting their fingernails trying to decide between a WordPress or Jamstack approach to building a website. We’re at the point where the technologies are well-understood enough that the process goes like:
- Put adult pants on
- Evaluate needs and outcomes
- Pick technologies