Views: 864
Number of votes: 6
Average rating:

Optimising your site for a global audience

I’d hope most people reading this understand the importance of web performance but, when considering how best to expand an existing site into new markets or to build a site spanning multiple regions, it’s easy to get caught up in the practicalities of localisation, etc. while neglecting the basics. High on the list of priorities for any site should be ensuring the site performs consistently well in all of the countries and regions it serves (not just where the main stakeholders live 😉) which, as I mentioned in a previous post, is not quite as straightforward as it seems, so I put together this post outlining some of the considerations and options available when building a site on a global scale.

Choose your location wisely

Probably the most commonly implemented of the techniques listed here (often combined with a CDN) is to simply choose a single central location to host your site. You take a look at where your traffic comes from and choose a location that best serves that traffic. This choice often comes down to what feels right though you can take a more scientific approach by estimating the percentage of traffic which would be best served by each of the regions in question, estimating the latency between the regions and calculating the impact of putting your site in each region. As an example, the traffic to a site breaks down to 50% EU west, 20% US East and 30% US West. Latency between the datacentres is as follows:

 

EU west

US East

US West

EU west

0

73ms

150ms

US East

73ms

0

70ms

US West

150ms

70ms

0

If we multiply the latency by the percentage of traffic, we can get a relative measure of the best location to choose where the lowest number is the best

 

EU west

US East

US West

Total

EU west

0 x 50 = 0

73ms x 20 = 1460

150ms x 30 = 4500

5960

US East

73ms x 50 = 3650

0 x 20 = 0

70ms x 30 = 2100

5750

US West

150ms x 50 = 7500

70ms x 20 = 1400

0 x 30 = 0

8900

Use caching effectively

To make the most of your site you should always consider how best to cache your content. Though the term caching may refer to either server-side caching or client-side caching, in this instance I’m talking about client-side caching. It’s not that server-side caching isn’t important, far from it, it’s that server-side caching is as important for an intranet site serving 50 people sat within a 20 metre radius of the server as it is for a global site serving millions of users around the world. One of the main challenges we face when delivering a site globally is network latency. The closer we can get to the browser we’re serving files to, the better and you don’t get much closer than the user’s machine itself. The more we cache on the user’s machine, the less outbound requests we’re making and the lower the impact of the network latency.

At its most basic, we can set cache headers on static assets, including assets like images uploaded to Episerver. To make the most of this cache we can set the expiry to a date in the future (say, 30 days) which means that, all being well, we shouldn’t need to call back to the server until the cache expires but there’s a catch. What if one of those cached files changes an hour after it’s been cached? In theory you’re stuck with it until the cache expires but in practice there’s a few things we can do. If we can encode a timestamp into the URL then, when the asset changes, the URL changes too meaning that the new URL won’t be cached and the file will be requested as though it were new. While this may sound complex to implement, the hard work’s already been done here:

https://github.com/bjuris/EPiServer.CdnSupport

Just add that module and a little bit of config and you need never worry about cache invalidation again.

Beyond simply setting caching headers on static assets, you may also want to consider how best to cache your page content. This can be a problem if your pages are entirely dynamic or heavily personalised however if your content is primarily the same for all users but with one or two personalised areas such as a shopping cart count/value or logged in user’s name, it may be better to load a cacheable generic version of the page without those parts then load in the dynamic parts using JavaScript.

Finally, if you need finer grained control over how you cache or load your content and assets, you may want to consider using service workers to manage a local cache or pre-fetching content and assets using a <link rel=”prefetch” /> tag.

Implement a CDN

If I could recommend just one of the techniques on this page it would be this one. Seriously, just do it. Even if you’re just serving a single region a content delivery network can dramatically improve a site’s performance (if you use it correctly). A CDN builds on the browser caching techniques described above by caching your content at edge locations closer to your end users. This means that you get a double-whammy performance boost in that there’s less latency between the user and the content and, just as importantly, your server isn’t having to handle requests for content cached in the CDN, freeing up resources to process requests which can’t be cached on the CDN.

There was a time not so long ago when using a CDN was pretty pricey but nowadays you can implement a CDN for almost nothing on the likes of Azure, AWS CloudFront and CloudFlare, or for literally nothing on CloudFlare’s free plan (though with some limitations). As if that wasn’t enough of an incentive, these CDNs often offer additional services either bundled or for a small additional cost. As an example, the paid CloudFlare plans (as included in Episerver DXC service) go beyond the basic caching proxy functionality of a traditional CDN and add DDoS protection, Web Application Firewall and image optimisation (e.g. automatically serving images in webp for browsers which support it), making your site even faster and more resilient.

Separate sites

While this option is simple and effective, there are many drawbacks. This technique involves setting up entirely separate Episerver instances, each running a site to serve a different location. You may choose to run them all on a shared codebase to make overall management easier but you’ll get none of the benefits of running a single instance covering multiple locales. As an example, there would be no option for a language to fall back to another if they exist in different Episerver instances and similarly adding hreflang tags to link between languages becomes a manual process which is near impossible to keep on top of. This will also have a cost impact in terms of Episerver licensing and infrastructure costs.

What you do get from this approach is a simple method for setting up sites with infrastructure close to your end users so, if your country sites are entirely managed by local teams and don’t necessarily have to share a common structure or interlink, this may work for you but I suspect that’s a pretty rare scenario these days.

Mirroring

A slight variation on the separate sites approach would be a technique I’m going to refer to as mirroring. Why? Well, back in the days when Episerver had to be installed through “Deployment Centre”, there was a feature called mirroring which allowed you to create content in one environment and transfer it to a different environment using a synchronisation service. Fast forward to 2018 and Episerver’s Mark Hall created a content synchronisation mechanism which gives you the benefits of mirroring while addressing some of the issues of the official (though deprecated) Episerver mirroring feature.

https://world.episerver.com/blogs/Mark-Hall/Dates/2018/6/simple-content-synchronization/

Though the solution here has been designed to allow a configuration without a CMS UI in the production environment, you could just as easily use it to create content in a single location and push it out to Episerver instances closer to your site users. Though this solves the shared/linked content issue from the separate sites approach, be aware that there will still be the same licensing implications.

Replication

If you’re running in Azure and you’re willing to accept the limitation of having only a single writeable region and having all others read-only then you could consider taking advantage of Azure SQL’s geo replication capabilities. This technique allows read-only replicas of your database to be maintained in different azure regions which, when coupled with app service instances in those regions, allows for duplicate but synchronised infrastructure which can be scaled out across regions. Unfortunately there are a few complications with this approach but, at the risk of being accused of blatant self-promotion, I wrote a blog post explaining how to use the existing components of an Episerver site in Azure to work around these complications.

https://world.episerver.com/blogs/paul-gruffydd/dates/2018/10/going-global--geographically-scaling-an-episerver-site-over-multiple-azure-regions/

Decoupling

So far we’ve looked at techniques which can be applied to an existing site with minimal changes but what if you’ve got a blank canvas? One option would be to look at decoupling the CMS from the website so that the CMS sits in a single location and is used simply as a data source with the rendering and serving of the content happening independently in locations closer to your end users.

With the advent of the Episerver Content API, this has opened up various options for us in terms of how we use content produced in the CMS with probably the most popular being to use single page app techniques to read data from the CMS and render it using libraries such as React, Vue or [insert name of JavaScript library-du-jour]. There are plenty of articles out there which explain the benefits of this approach so, in the interests of balance I feel I should point out that single page apps aren’t a silver bullet. Without effective planning and caching between the app and the Episerver instance, this approach has many of the same pitfalls as simply rendering the site using razor on the server in that the data still needs to be requested from the Episerver instance and that data will be subject to the same network latency we were trying to avoid. Done well though, you can get some great results.

Taking a slightly more extreme approach, Allan Thraen’s post explains how you can publish static HTML out of an Episerver instance and, as I think we can all agree, nothing scales quite as well as static HTML. As with the replication option above, this technique results in a read-only site and, if you’ve got hundreds of thousands of pages of constantly changing content this may not be the right option for you however, for smaller, more static sites, this would be easy to scale out and cost next to nothing to host.

https://www.codeart.dk/blog/2018/9/episerver-static-web-site-generator/ 

What next?

If you've made it this far - well done. Hopefully you've got an idea of some of the options currently available to you either individually or in combination but you’d be forgiven for thinking that this all seems like a lot of work and that there should be just a setting hidden away in Episerver admin that sorts this for you. Well, though it’s not going to happen overnight, there are some interesting developments in this area. You may have noticed that most, if not all of Episerver’s newer products and features have been built as independent hosted services and that approach is likely to extend beyond new features into the core of the CMS and Commerce.

At last year’s Ascend events, there was talk of a plan to create an externally hosted order service for Episerver commerce to handle the ordering process separately from the installed Episerver site so you can still take orders even when your site is in read-only mode. Fast forward to February this year and that order service had become a reality which was demonstrated at the Partner close-up event in Stockholm. Alongside the order service there were rather more subtle mentions of a hosted content service and, though there are no details of this service beyond describing a suite of independent microservices based on .Net Core, it wouldn’t be unreasonable to assume that it would be built in such a way as to allow for geographical replication. By taking a distributed approach, it reduces the risk from a failure of a single region and paves the way for the next generation of distributed web applications making it a win-win-win for Episerver, partners and customers.

May 02, 2019

Please login to comment.