Google’s AMP is an attempt to improve the performance of articles on the web.

I don’t want to go into the politics of it here - not that it isn’t very important, just that others have already written about it already and much better than I could. Instead, I want to discuss the AMP client-side model and what I think about it, particularly in comparison to React and so-called isomorphic Javascript approaches.

SSR and Isomorphic JS

Server-side rendering seems to be incredibly popular at the moment. The idea is to use React (or equivalent) on the client-side but with a faster first paint (and FMP) than would otherwise be possible. The way this works is that initial markup is produced on the server, using Node/Express.js for example, and then the client-side framework binds or ‘hydrates’ this on the client to introduce any dynamic behaviour.

SSR is both an architecture and a technology choice and there are significant pros and cons associated with it.

In constrast, AMP doesn’t allow custom Javascript at all and promotes a strict separation between server and client-side concerns.

AMP is explicitly designed for publishers and article/blog-style content and it does seem well-suited to that space.

But we also see notable publishers choosing the SSR/React-all-in model. For example, the NYT site is entirely React-driven in this way.

The two approaches are entirely, completely, at odds it seems, but appear to be operating in the same space!

Lessons from AMP

As a self-professed full-stack* developer and, at the time of writing, tech-lead for, I’ve been thinking about which approach is best for my beloved Grauniad. And I’ve come to the conclusion that the AMP approach is ultimately the better way for us.

By ‘AMP approach’ I mean loosely: a server-side that produces markup, and dynamic behaviour introduced by markup-driven web-components on the client-side. I do not mean the exact AMP libraries and that specific implementation. If you are not familiar with how AMP works, it is probably worth taking a brief look at some of their examples at this point before reading on.

This conclusion is of course specific to our context:

So why do I like the AMP approach and what are my concerns with the SSR/hydrate alternative?


Architectural decoupling is the most important thing when it comes to agility over the medium-long term for larger software services.

Isomorphic Javascript is, unfortunately, a coupling disaster:

If you are producing a SPA or highly-interactive website, then the isormorphic approach may justify itself, but a publishing site is not such a great fit. The short-term benefits of the isomorphic approach are likely to be dominated in the medium-long term by the coupling constraints and eventual forced re-write down the line.

In contrast, AMP is relatively decoupled:

Web components are a web standard and can be (re-)written in any combination of client-side technologies.

The great thing here is that you can mix and match technologies across the entire stack. Want to try out using Python to generate markup for one section of the site or page type? Easy! As long as the relevant markup is the same, the client-side behaviour will stay the same. Want to experiment with using a new library to build some of the web-components? Again, it’s easy to do this alongside your existing technology choices.

We should be very cautious about foregoing these important forms of decoupling in our architectural choices.

An important caveat is that AMP is not fully decoupled; a core runtime is still required to manage performance-critical operations - network requests and DOM operations.

Isomorphic Javascript approaches are aware of some of these problems and some of the solutions include lazy or partial hydration, and easier ways to ‘eject’ out of the framework to run custom/self-managed client-side code. I’m very cautious about buying into such complexity and not convinced they address the coupling concerns (they are more about improving client-side performance).

Software engineering

Russell Cox, of Go(lang) fame, has defined software engineering as

what happens to programming when you add time and other programmers

It is a human problem, but nonetheless critical, to ensure good performance of the site as new features are added over time. Experience has taught me that convention is an ineffective solution to this problem.

The key assumption of the AMP-approach here is that, for a publishing site, the vast majority of client-side behaviour can be encapsulated in a small set of client-side components.

Provided these components are well-written and performance tested, developers can add client-side behaviour without the risk of damaging client-side performance.

A core web team can steward these components without having to review every PR (which is in any case unrealistic).

Now, of course it is possible to introduce linting, or other tooling approaches with SSR to achieve something similar. But I much prefer the significant layer of friction the AMP approach introduces here to adding new client-side behaviours.

Before you write me off as some kind of control freak, it’s worth remembering that performance is absolutely crucial to our core mission so it is worth being radical to help achieve it. Fast performance is hugely associated with improved engagement, it ensures people with poor connections (more likely in poorer countries) can still access our content without it costing a fortune and/or taking forever to load, and it significantly impacts our SEO performance too.

Write once

A smaller point, but relevant to our case, is that our client-side DOM operations are typically write-once. For example, after page load we augment the core content with what we call ‘onward-components’ - things like ‘most popular’ lists or ‘related content’. VDOM approaches are simply irrelevant to this kind of use case and yet can add a lot to your Javascript bundle size (at least in the case of React DOM). And, if the majority of your page is static, as in our case, then hydration - at least in the naive implementation - is a pointless expense.


One motivation for Isormorphic JS, and something the NYT cite in their blog posts, is the desire to use a single codebase across multiple-platforms. React Native is increasingly powerful and offers the promise of one codebase but with native behaviour on web and app (and potentially other platforms too).

I’m not familiar enough with React Native to comment on this in detail, although the scope of this kind of solution seems ambitious; it seems likely that any abstraction across platforms will be quite leaky.

But I’m not aiming to criticise the NYT here! Our product offerings are quite different. The NYT site is a premium experience - they have a (partial) paywall - so it may well make sense to aim for a similar app and website experience. In contrast, the Guardian website and apps are very different. Our website is entirely free, whereas the apps are designed to be a premium experience. The audiences are very different; one is largely unknown and irregular, and the other is known and loyal. It is difficult to see this product strategy changing in the near to medium term so standardising on a single technology for the two doesn’t make sense in our case.

Can I still use Node?

Some of you are reading this and thinking: this is all really obvious! Isomorphiic JS is meant for highly-interactive sites (‘apps’) but not for news sites!

And basically, I think this is right, albeit the arguments are subtler and the tradeoffs larger than people sometimes realise.

I do want to add though, that there is still very much an argument for using Javascript-based technologies on the server-side. Even if you don’t adopt SSR, Node, JSX, and CSS-in-JS can be really great:

What’s more, if you stick to non-isomorphic JS, the usual JS tooling nightmare (webpack, babel setup to do hot-reloading and all the *-ifications) simplifies dramatically.

* I use this term loosely. My background is as a server-side developer, but for the last couple of years I’ve been working on both client-side and server-side concerns and so now have delusions of client-side mastery.