I'm a long time server-side developer who've been working on the front-end for the past 6 months.
I don't agree with this article. I think its author has a significant misunderstanding of SPAs and overstates some of the potential issues. Having built both type of applications at varied level of complexity I absolutely don't agree with the notion that SPAs are necessarily more expensive than MPAs. I'll address a few of his points, but most, if not all, of his claims can similarly be refuted.
Statefulness: Few people would build an SPA on top of a stateful backend? Most SPAs query an API which nowadays will more than likely be hypertext driven (read stateless). The user authenticates, gets an access key, then serves that access key along with each subsequent request to the API that needs it. The server does not keep a session around. It receives the query, does its job in the confines of what is requested and serves back a response (likely in JSON). That's more or less it. There's very little state involved here.
Testing: Vague unsubstantiated claims. Why make backend and frontend talk to each other when mocking would do just fine.
Performance and network latency: Has anyone been using an SPA recently and had this as their main problem? If your client is incessantly polling your API, then it's a sign that either your API is not designed well enough to address the problem domain, or you need to employ a caching mechanism on the front. There's no cookie cutter way to architect an API. If your client is more likely to query and use 10 items from a collection, don't force it to make 10 requests, provide a facility to bundle them up into one. On the front-end most frameworks have satisfactory libraries to handle state and cache management.
Slow first time load, multiple times per day? Stop updating your live bundle multiple times in a single day.
Authentication with JWTs: JWTs are not an SPA requirement, they're just one of many approaches to authentication. I don't use them and don't see the point of them in most apps that I've built. If you do use them and need to keep track of them (maybe because you'd like to be able to invalidate them), store them in something fast like Redis on the server.
State updates: The JavaScript ecosystem has excellent caching facilities, that can automatically poll and update resources upon a timeout. It's indeed not rocket science.
Error Handling: You catch the error from the http response and call your handler. That's practically like muscle memory whenever one does an http request.
client.get({url}).then(resp=>{
// handle response
}).catch(error=>{
errorhandler(error)
})
No busywork there and probably much more user-friendly than that default error message that will be served by nginx (if one truly wants to stick to such a "no busywork" philosophy).
The rest of the article can similarly be addressed.
My conclusion is simply that if you want to maximize your cost efficiency, build a team that is familiar with their tools. If all your developers have done and are familiar with are MPAs, then yes, it might be more costly to build an SPA for them at first. I should know. I went through that phase at the beginning of my recent JS foray. Doing anything was slow and would've taken me a fraction of the time by simply playing around with Jinja on the backend. But fast-forward a few months, after immersing myself a bit more with the ecosystem, I cannot imagine reverting to that approach to build anything more complex than a simple data driven app. Emphasis on the simple.