There's quite a lot of talk these days about Single Page Applications (SPAs) and the terrific user experience they deliver. This is great, and the SPA architecture is probably a good fit for many apps, but I want to point out two reasons why SPAs are harder to develop and maintain than traditional server-side web apps, and why they will always be harder regardless of new JavaScript frameworks and other technologies that become available. If you're considering a SPA architecture, remember to weigh this additional difficulty against the user-experience benefits you'll get. For the typical line-of-business app full of big forms and complex data the traditional choice could very well be the right choice.

First Essential Difficulty: An Additional Logic Tier

In all but the most trivial apps, if you build a SPA, you'll need three tiers of logic instead of two. I'm defining a logic tier as a physical tier that contains "business logic" specific to the features of your app. In a traditional web app, regardless of your web server platform, MVC framework, etc., if you want to add a customer editor (for example) to your app, you need to add some database tables (data tier) and some code that builds HTML and handles form submissions when users make changes (web server tier). In a SPA, you'll obviously still have a data tier, you'll have a web server tier that exposes the data via JSON or XML web services, and finally you'll have a browser tier with some JavaScript-based code that presents the data to users and handles updates.

Let's consider the code for a simple, read-only display that shows a customer and some orders.

Traditional Web App

On the web server:

var customer = retrieveCustomerFromDatabase(); addCustomerToHtml( customer ); var orders = retrieveOrdersFromDatabase( customer ); addOrdersToHtml( orders );

SPA Equivalent

On the web server:

var customer = retrieveCustomerFromDatabase(); addCustomerToJson( customer ); var orders = retrieveOrdersFromDatabase( customer ); addOrdersToJson( orders );

And in the browser:

var customerAndOrders = retrieveCustomerAndOrdersFromWebService(); addCustomerToHtml( customerAndOrders.Customer ); addOrdersToHtml( customerAndOrders.Orders );

With the SPA architecture, you essentially have to deal with the customer and the orders twice. It's not that you have to do any of the mechanical tasks twice: you're still only retrieving the data once and building the HTML representation once. But you must now publicly present your customer and orders from both the web server tier and the browser tier. If you add a new type of data to your customer display, such as a list of shipping addresses, you need to add the addresses to the JSON and the HTML. If you need to restrict access to a field (e.g. social security number) such that only certain users can see it, you need the authorization check twice, once when writing the JSON and again when building the HTML. In a traditional web app, you can go straight from the data to the final HTML representation with a single block of code on the web server. Here's a diagram that sums up the difference: