Hey @tleish! A little late to the game here, but I figured I’d chip in.
The only accurate answer here is, “It depends”. It depends on your application’s flow, whether using a frontend framework requires more or less calls to the backend (I’ve seen many instances where it requires more - these days the solution usually ends up being sticking GraphQL in there to help, which can open up a whole other can of worms). Often times, the API calls returning JSON end up fetching and returning more data from the database and/or remote services than is needed (especially for lists), which can slow down backend response times, or a single page ends up making multiple calls to the backend vs. a single call that might be made in a Stimulus/Turbolinks-type world. Of course, there are ways around this (the backend for frontend pattern or the more general GraphQL approach), but that assumes the time and knowledge is there to implement those. Often times in a tight timeline, the simplest approach is taken (at least initially). My gut feeling is you’re more likely to run into issues scaling the backend with an API + JS approach, based on my experiences. But, as I said, it really does depend.
Personally, scalability (over an API + JS approach) isn’t something I’m concerned with when starting a new project with Stimulus and Turbolinks. In my most recent experience, we had a higher traffic site that used Stimulus and Turbolinks that was much easier on the backend than another team’s lower traffic Rails API + React (and in one instance + GraphQL) app, but I don’t have data to quantify it.
Prior to that, I worked for years on extremely high traffic Rails apps that served global audiences at Disney. Rendering HTML on the backend vs. rendering JSON was never a decision of scale in those cases (and load was something that had to be estimated and stress test before launch, it was taken very seriously), it was just about the business case and what made sense. Again, no quantifiable data.
In regards to caching, it’s unlikely that you’ll need that due to performance differences in rendering HTML vs. JSON. Rather, you’re more likely to need it due to data access (database or remote services). With a Stimulus app, it’s easier to optimize for this because each controller action can just query for and render only the data it needs. With a typical REST API, you’re often fetching and returning more data than you need without the opportunity to optimize it for each page (again, without relying on other patterns/technologies) and thus caching might become more of a requirement rather than a nice to have for acceptable performance.
This isn’t all to say that you can’t have blazing fast APIs. You certainly can. But blazing fast never comes free, regardless of the approach.
Anyhow, these days I prefer to stick with the simpler approach (Rails/Stimulus/Turbolinks) unless there’s a business reason not to (e.g. the need for a public-facing API - in which case, I’d still likely have my apps use Rails/Stimulus/Turbolinks and just consume the API in Rails). So far, so good. Your mileage may vary.
Cheers!