« another approach to replication | Main | Olympic Site Architecture »

How Scalable are Single Page Ajax Apps?

I've been using GWT for an application and I get the same feeling using it that I first got using html. I've always sucked at building UIs. Starting with programming HP terminals, moving on to the Apple Lisa, then X Windows, and Microsoft Windows, I just never had IT, whatever IT is. On the Beauty and the Geek scale my interfaces are definitely horned-rimmed and pocket protector friendly. Html helped free me from all that to just build stuff that worked, but didn't have to look all that great. Expectations were pretty low and I eagerly fulfilled them. With Ajax expectations have risen again and I find myself once more easily identifiable as a styless geek. Using GWT I have some hopes I can suck a little less.

In working with GWT I was so focussed on its tasty easily digestible Ajaxy goodness, I didn't stop to think about the topic of this site: scalability. When I finally brought my distracted mind around to consider the scalability of the single page webs site I was building, I became a bit concerned. Many of the strategies that are typically used to achieve scalability don't seem to apply in single page land. Here are the issues I see. Maybe you can tell me where I am off in my analysis?

  • Plus: a lot of state is maintained in the client. You don't need to keep session state on the server side. This is a win because you aren't slamming the database to reconstitute state. It's cached on the client. After more consideration it seems this is not always the case. Take your typical shopping cart scenario. You have the old problem of not storing prices in the client so some evil Mallory can attack your system by changing prices. And my shopping cart must outlast my browser session so its still there when I return. I would be heart broken if my carefully crafted Amazon cart disappeared every time Firefox went away. So server side state is often still necessary. Yet a lot of state is kept on the client side and that's a better thing.

  • Plus: a lot of business logic in on the client. The client can do a lot of the work which saves making calls to the server. An interesting comparison of the effects of Ajax on business logic partitioning is Google Calendar: Not As Fat as Other Ajax Apps by Dietrich Kappe.

  • Minus: Can't offload searching. The lack of a proper link structure means your site can't be spidered, which means it can't be searched. One useful scalability strategy is to offload search to something like Google's Custom Search Engine, not for the ad revenue (because there's little), but because it means I don't have to devote any resources to searching. That's a huge win.

  • Minus: SEO problems suck up developer time. The common response to the previously mentioned search engine optimization (SEO) problems are to make a shadow text site or insert hidden divs. But that's a lot of pretty useless effort. I would like to spend my time elsewhere.

  • Minus: Can't load balance static content from the client. RPC is used to slurp up data from the server and these requests must go back to the originating domain. This counters one common strategy of using a CDN and/or multiple host names for serving content so you can trick your browser into starting multiple simultaneous connections to different hosts when loading page content. This speeds up your site and spreads the load across different servers. Using RPC to serve content seems to lose this advantage.

  • Minus: Ajax calls add server load. You buy into that with Ajax, but it's still a concern, especially if you have to poll frequently for updates. Dietrich found that the Ajax requests may not be that much smaller than before, so you can't depend on smaller work loads to make up for the increased number of calls. See Yahoo Mail, Ajax and Your Server.

  • Minus: Lack of monetary scalability with AdSense. Without a page to parse AdSense can't figure out which ads to display on your site. So one common monetization strategy isn't open to you.

  • Unsure: When using a caching proxy like Squid, a major scalability strategy, is my cacheable content effectively cached when using RPC? I couldn't find a resolution to this issue.

    One solution around many of these problems is to use a combination of REST and JASONP. This converts your client into a big mashup, even if all the parts you are mashing are your own. And this approach makes a lot of sense to me, but then I don't really see the purpose of having a RPC mechanism.

    There are surely issues I've missed and misunderstood, but it seems single page apps present some distinct scalability challenges. Your thoughts would be appreciated.
  • Reader Comments (7)

    GWT is the">Google Web Toolkit for anyone not familiar with the jargon and confused by the tag link (as I was!).

    The SEO issue is huge. Particularly if you're building large scale content sites. Although, arguably, those sites perhaps don't benefit so much from AJAX. However, if you've built the app to degrade smoothly, so it can be accessed from a Treo / text browser, search engines should still love it!

    I believe you can load balance the requests to multiple back end servers. I've read (possibly from a link on this site) that it might require the use of iframes or something of that ilk to smoothly pass the request to multiple domains. I believe it can be done anyway.

    I suppose the conclusion is the same as always, don't use the fancy new technology for the sake of being fancy!" title="Callum" target="_blank">Callum

    November 29, 1990 | Unregistered Commenterchmac

    I'm not a developer but I used GWT 1.3 extensively for one of the internal projects. The things I didn't like were

    - Monolithic. Lazy load is still not implemented (atleast not in 1.3). That made it close to a fat client.
    - Developers are usually not the UI designers... but in GWT u are forced to
    - Didn't allow me to change stylesheets on demand
    - Maintaining state was easy but making it bookmarkable using history tokens was a pain after sometime
    - Loading time increased with the complexity of the app

    My days with GWT are kind of done. I'm back to PHP... atleast for a little while.

    November 29, 1990 | Unregistered CommenterRoyans

    Callum, I agree with you. I don't see the purpose in building a page out of Ajax unless you are just getting a lot of benefit from it. So, for example, if I had a content page I'd probably not use Ajax, but perhaps a search form would benefit from it. If you split that up, some of the SEO issues go away as well.

    That said, people are still going to use a lot of Ajax. :)

    I'm curious about some solutions to these problems as well.

    Dustin Puryear
    Author, "Best Practices for Managing Linux and UNIX Servers"

    November 29, 1990 | Unregistered CommenterDustin Puryear

    I think maybe you are thinking of using AJAX in the wrong scenarios. If you have a SEO/content type of site that needs the capabilities of being spidered and such then perhaps AJAX isn't for you. Where AJAX really shines in a single page app, is just that, an _application_ and not a commerce site per se. In this case I'm thinking of back office type of applications as opposed to broad content type of applications. Something along the lines of 37Signals style apps as opposed to a blog or brochure-ware.

    That doesn't mean you can't use AJAX or other javascript goodness on a content site, but not to the extent that you would write a single page app.

    November 29, 1990 | Unregistered CommenterRobert

    AJAX itself can be used for good or evil. Used well, it can improve your scalability.

    Here are a few things to watch out for:

    1. Use AJAX techniques to replace equivalent page views. Small XML or JSON responses will be much lighter weight than entire HTML pages. This reduces your bandwidth needs and makes for very low latency in the app server.
    2. Beware whizzy features like autocompletion. Even small, fast requests will pile up when you start making a request to the app tier every time the user pauses during typing.
    3. Stick with external JavaScript files. Don't pile a bunch of JS code in the page itself. External files can be cached at the edge (by a CDN) or by the browser. JS code in the page has to be sent over the wire on each request. (The same goes for CSS, too.)

    If you follow these guidelines, then AJAX will reduce the load on your servers, improving your overall capacity.

    Michael T. Nygard

    Author of "Release It!"

    November 29, 1990 | Unregistered CommenterMichael Nygard

    > Here are a few things to watch out for

    Those are good points, but hard to follow :-) I found it natural with GWT to do everything within GWT. I looked into using GWT for just the AJAX components, but it seemed to make more sense to use one of the many libraries (dojo, yui, ext, jquery, etc) instead.

    November 29, 1990 | Unregistered CommenterTodd Hoff

    I co-developed a single page web app that we host for use by our business customers. In addition to internal use apps, I think this is a perfect use for GWT. We've also developed similar applications in Flex/Flash, which is also not a bad choice, but I wanted this particular app to have a more like a normal web UI.

    One of the biggest problems we ran into came from our desire to use standards mode rather than">quirks mode. The GWT development team chose to initially focus on quirks mode rather than standards mode, though they plan to improve standards mode support in a later release. We found quirks mode to be just too, well, quirky, to deal with, so we toughed it out and worked around the GWT issues with standards mode. Our CSS ended up being far more sane after we switched to standards mode, although we did have to replace many of the built-in GWT widgets with our own. IE 6 behavior is still a little wacky, but at least we can get most of our users to go with Firefox or IE 7.

    Also, the performance enhancing image bundling feature built into GWT 1.4 was unusable for us in standards mode. Images were too often cropped or positioned incorrectly. Our app doesn't have a lot of images, other than dynamic graphs rendered via GraphViz, so giving up image bundles didn't cost us much, performance-wise.

    We avoided XMLHttpRequests for individual keystrokes, choosing to go back to the server only when a field lost focus. Google can afford all the servers to handle the load for that, but we didn't want to.

    Keeping state on the client is quite easy with GWT, though it's tempting to go crazy and cache too much. Then you have to deal with keeping the client in sync for scenarios where the data can also be changed outside of the client.

    One major thing to watch out for is allowing asynch requests when you really need them to be synchronous. If your app allows the user to perform several actions in quick succession that all result in GWT RPC calls, you need to be aware that these calls could get handled not in the order they are sent to the server. To work around this, we built a synchronous command queue on the client that we use to synchronize all the commands that actually need to be synchronized. You get all the non full page refresh goodness without all the bad out of sync, inconsistent, corrupted data and confused, irritated user badness.

    Another way to synchronize actions is to throw up a page-sized transparent gif to temporarily keep the user from continuing to interact with the app, but I found that to be really annoying except in obvious cases where you want modal dialog behavior.

    November 29, 1990 | Unregistered CommenterRobert Stewart

    PostPost a New Comment

    Enter your information below to add a new comment.
    Author Email (optional):
    Author URL (optional):
    Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>