We’re going to use this engineering sub-category of the DailyStory blog to share some details about the process that goes into building our platform.
Like most software this has been a journey
I had the benefit of working with some incredible engineering talent at Telligent. I was also able to learn a lot about running high traffic web applications at scale from some of our customers (Xbox, WebMd, and many others).
I’m by no means claiming to be the best at designing or writing software, but hopefully by sharing my experiences building DailyStory I can get some feedback (or help some other people along their journey).
Built 100% on the Microsoft platform*
I decided early on to build DailyStory on the Microsoft platform.
True, it’s been a few years since my days on the ASP.NET team, but .NET is both a platform I know and platform that can scale. The other decision I made early on was to built 100% on Azure.
When I say 100% I mean in a way that fully utilizes everything that Azure can do natively. There is no design consideration for making the software portable to other platforms.
Why? At Microsoft I wrote the first versions of Community Server after introducing (modeling) the Provider Design Pattern for Microsoft .NET 2.0. The thesis behind that pattern, which is still in .NET, is to enable various “providers” to be swapped out for a given API, e.g. Membership. We did the same thing in Community Server early on with the intent of someday supporting a database other than SQL Server.
The problem with this concept is it is too often a “you can, but you won’t”. So, I could design DailyStory to run in other environments like Amazon, but most likely won’t. Instead, I’ll use all of what is available in Azure; even if it means committing myself to the platform.
So what does 100% on Azure mean? Azure Web Jobs, Queues, Table Storage, Blog Storage, SQL and of course all the goodness that comes with Azure web apps.
The DailyStory application itself it written using Microsoft MVC and fully utilizes all the new ‘goodness’ available, such as async/await for any out-of-process REST, SQL, etc.
Data center-bound tenant design
In addition to the Microsoft platform decision, I made the early decision to follow a multi-tenant design pattern that binds tenants to a given data center.
I’ve done vertical scaling, it’s not fun. DailyStory will scale by horizontally partioning tenants across commodity hardware.
At a high-level, all requests are first authenticated through a shared login service and then directed to the data center that is best for the end customer.
Azure makes this very easy given their global data center footprint.
From an application perspective new tenants are created in a data center that is physically closest to them, for example, (us-1, us-2 and uk-1). All the related resources for that tenant including its queues, sql, etc. are all within that data center.
This means that as the application grows, rather than scale the software by adding more memory, CPUs or storage we can simply create more nodes. Furthermore, as different tenants require different resources they can be moved to different data centers.
This adds a level of resiliency to the system. If, for whatever reason, one of the Azure data centers is unavailable it doesn’t necessarily mean that all data centers are unavailable – which also makes updates nice because application updates can be scheduled at the best time for the region the data center is in.
Did you see the asterisks?
Ok, I said I was building it 100% on the Microsoft stack. But I did put an asterisk next to that statement: I’m not giving up my Mac and I’m limiting my use of VMs.
So 100% of the development for DailyStory is using Xamarin on the Mac using Mono. And it’s been awesome. Technically Xamarin is now part of Microsoft, but that only happened last year.
A small side-bar: I’ve also been using Visual Studio Code quite a bit too.
This has had its fair set of challenges though. To name a few:
- Nuances between how Azure and XSP4 handle dead locked threads from synchronous calls to async methods that return .Result.
- Known Mono bugs in how XSP4 unloads the page output cache.
- XSP4 getting “lost” when trying to find the MVC View on async calls that do async stream reading/writing.
But, overall, it’s is surprisingly stable, usable and reliable.