The combination of these four technologies – Angular front-ends hosted on Azure Blob Storage, serverless Azure Functions, backed by Azure Table data – is a pure powerhouse resulting in high-performance, low-cost, and rich user experience. If you’re still building applications in the traditional web application monolith backed by a relational database and wondering why the cloud is so expensive, this post is for you.
Angular
Since the initial false start that was AngularJS, the Angular team, now on version 6, has rebuilt confidence with the market and delivered nothing but stable, compatible, increasingly easy-to-use, and increasingly performant updates. The learning curve for entry is nothing near where it was with AngularJS. Case in point, the new routing engine is no longer one of the most complex features but rather one of the least complex. Most seem to agree that RxJS, while not officially part of Angular, is a must-use library for managing asynchronous calls. Unfortunately RxJS does have a high learning curve so make sure you allocate time for your development team to learn it or you’ll be rewriting a lot of underoptimized, difficult to read, and buggy code later on. Another must-use plugin is the Material design system. Not so long ago, Bootstrap was my go-to and I still love it. After working with Material for a few weeks, I have a new favorite. Long live Material! NOTE: If you’re on Bootstrap today, I don’t recommend switching all of your production code – more of a recommendation for new products.
I’ll also mention AngularCLI here, but honestly I don’t even feel this is optional anymore. AngularCLI not only builds and serves your Angular code, but also offers a significant cost savings and consistency gain in generating templates for you. According to Google, there are alternatives to Angular CLI (WebPack, React Router, and styled-components). Keep it simple. Use AngularCLI.
Azure Blob Storage
There are quite a few ways to host a static website on Azure – a VM (highest cost), Azure App Service (next highest), CDN, and Azure blob storage. The last two are by far the lowest cost, and interestingly, the best performance. Like, by far the best performance. The ability to host static websites on Azure blob storage has been in place for some time in a sort of hacky way, but the Azure team has listened and made this a first-class use case. The process for setting it up is simple and is described in detail on Microsoft’s website. The best part is the cost. For the highest tier – RA-GZRS – it will cost you around $.03/GB and less than 1 dollar for bandwidth (may change based on your requirements). But for the 99% of us, it’s less than $1/month for 99.99x SLA.
Azure Functions
Those coming from a Microsoft .NET Core Web Application or Web API background will find it a fairly smooth transition to Functions, albeit with some “who moved my cheese” moments (no config file, no Startup class for dependency injection). Suffice it to say, there are ways of doing both provided in the links, they’re just not built in. It can also be frustrating to have the 1 function, 1 file limitation, but I found as the codebase grows this is actually a good thing. It forces a separation of concerns and adherence to the single responsibility principle. Once you’re up and running, you will find some awesome features (timer triggers) that you wish you had all along.
The pricing, while admittedly confusing, is quite advantageous for most applications. It’s based on GB-s (gigabyte seconds) and total executions, but there is a free tier that could last you a long time. The pricing will vary based on your application and you should seek to limit the execution times and number of calls using things like asynchronous programming and browser or distributed server caches for data that changes infrequently. I encourage you to run your application against a production workload to benchmark the consumption model. Add in logging so that you an gain insight into which functions are consuming the most resources and use that information to optimize. If you want more predictable pricing, you can run Azure Functions under an App Service Plan, more like traditional IIS. If you do that, it’s going to start at $75/month for 1 web server. Azure Functions and an app service plan running on a single web node have the same 99.95% SLA. Azure Functions require a storage account and so geo-redundancy is tied to the redundancy of the storage account, while the app service plan redundancy is achieved through load balancing using Azure Traffic Manager.
Azure Tables
I have been using SQL Server for years with a lot of success. When I switched to Azure SQL, I started looking for alternatives. The features are there, but the cost and performance is unacceptable. CPU and memory seem to be fine, but for anything I/O bound, it simply doesn’t perform. I’ve spent more time than I care to admit researching, tuning, and talking to Microsoft reps about this but the only advice I seem to come across is increasing the tier (which is expensive and doesn’t always solve the problem), and using some of the advanced features like in-memory OLTP and Columnstore indexes (also requires a higher tier). Because of this, we identified the need to auto-scale Azure SQL on a schedule, which is described in a previous post. Some would call this the “power of the cloud” – being able to auto-scale to save cost. Call it what you will – the performance doesn’t match the cost. If you need to use a SQL Server, I recommend using a VM right now.
Enter Azure Tables – a NoSQL key-value store for rapid development using massive semi-structured datasets. But don’t let the key-value part throw you off. When accessed from C#, you can query any column just like you would SQL, albeit the only indexes are on the Partition Key (usually the customer for enterprise applications) and the Row Key. I have not performed a load or volume test against Azure Tables, but from what I’ve seen it’s more than acceptable for the first version of most enterprise applications. If you need large-scale reporting, you’ll want a data warehouse like Snowflake or Azure Synapse (preview) anyway. So why not save cost and use Azure Tables for your OLTP.
The pricing of Azure Tables is between $.05-$.06/GB, dirt cheap for data, and about $0.03/million transactions. You could easily pay $2,000 – $5,000 / month to get started in Azure SQL. Yes, you lose full transaction support. Yes, you lose fine-grained index controls. Yes, you lose referential integrity. For mission critical applications, that may be enough to warrant the extra $50,000 per year or more.
NOTE: Microsoft introduced a “premium” version of Azure Tables included in CosmosDB, which comes with automatic secondary indexes and throughput optimization. Admittedly, I find the Cosmos pricing model to be confusing and haven’t spent enough time understanding it yet. What I don’t know is whether the move to CosmosDB for premium table storage indicates the end-of-life for traditional, cheap table storage. I certainly hope not, but something to be cautious of.
Azure Tables
Whether you’re looking to make your first leap to the cloud or looking to manage your cloud spend, the stack described in this post should be considered. I welcome any comments below on whether others have found success or limitations with the technologies listed. Thanks for reading!