Azure vs. AWS - First Impressions

If you have worked in a big company for your whole working life, you may not now what it is like to write software for a small business which mainly builds custom tailored solutions. As someone who worked at such places for almost six years now let me tell you about something that happens regularly in those companies: One peaceful day your boss will kick in your (virtual) door (the covids is still running at the time of writing) and proclaim “I’ve got a new customer that needs a piece of software, like, YESTERDAY!”. You, a veteran of a thousand psychic wars many commercial projects, will not even bat an eye.

“That doesn’t sound too bad”, you’ll tell your boss (hint: it never does when a CEX briefs you) when he is done filling you in. “That’s great”, he will say “You should be done in two weeks, right? Oh, and by the way, the customer only uses Azure, that shouldn’t be a problem, I suppose?”

“Azure” I sigh as my gaze wanders from my open ZSH shell to my AWS documentation printouts to the Tux that is standing guard over my workplace as I slowly slide down my chair, safely out of line of sight of my webcam.

Microsoft. The arch-nemesis.

But if the customer demands it, there is usually no room to negotiate as a developer. Thus, it must be done.

Drawing The Frontline

What will follow is a “first impression”, if you want to call it that way. This is by no means an objective, but rather a highly opinionated view of someone who worked quite a bit with AWS and suddenly had to get up to speed with Microsofts big blue platform fast.

So, lets start with my (slim) requirements: I’ll only need a way to serve a public API, run some code in the cloud and an SQL Database to store a rather small amount of (user generated) data. No IoT Device management or BI functionality fizzbuzz. Preferably completely serverless, as we didn’t know how many users would end up using the service after its release, and we wanted to be prepared for rapid growth. In an AWS world these services would be called “API Gateway”, “Lambda” and “Serverless Aurora”. Ironically, azure maintains a page where you can look up the AWS equivalent of all their services.

Off To Enterprise Wonderland

My biggest fear when starting out was that I would need to dust off my old, once-booted windows installation that was rotting on my company laptop as I expected MS to distribute their development tooling only for Windows. This fear at least seemed to be unfounded, as their CLI is available (even packaged) for a lot of distributions. Hell, it is even available on GitHub and thus as a nixpkgs package.

Then next step was to find a way to run serverless code. Azure suggests their “Functions” as a Lambda replacement, so I went with this service. And I have to admit that it is a pretty good replacement. This initial impression was mostly shaped by the Azure Functions Core Tools, a tool which allows you to run your function code locally with the same engine and routing used in the cloud. If you have ever tried to get some code running in a AWS Lambda you may know that most of the time you’ll have to log the input into your function, upload a new version, run the code in a lambda, wait for cloudwatch to update the logs, check the uglified output just to know how some input parameters from the orchestration engine are formatted. Granted, if you are using SAM templates to deploy your infrastructure, you can simulate API Gateways and Lambdas, but this feature is far from perfect.

Meanwhile, I continued to be pleasantly surprised by Functions. Not necessarily because it had a million additional killer features, but because it continued to be well documented and well-structured. The graphical interface Azure provides for Functions on their website is extensive and has a lot of sub-views, but they are always ordered and named in the same way across all their services. This may not seem like a big deal, but just go ahead and compare the AWS console for the IoTCore, Lambda and EC2 services. Three completely different applications with three completely different designs, different structures and click flows as if the teams that work at AWS never talk to eachother. Knowledge you may have acquired for one module, e.g. about how to limit access from the public internet to your resource, is useless in another. In Azure, in all relevant services there is a “Networking” view, in which you manage the networking.


A part of the Azure navigation sidebar, which is the same for most services

So all is well and Azure is the greatest piece of services ever bestowed upon humanity? Sadly, it isn’t. It’s still Microsoft we are talking about, remember?

First, there are the nearly comical little things that sometimes go wrong. Like the permission management that sometimes needs a solid 4 hours to apply changes (and seems to be stuck on “registering…” in the meantime) or the time it takes to provision a “““serverless””” Database.

Speaking about Databases, we haven’t talked about my SQL experience yet, have we? As I said in the beginning, I wanted to use as many serverless services as possible. This was especially important for me for the database as a) database instances are EXPENSIVE and I don’t like them idling around when the traffic is low during the initial phases of a project, b) scaling them afterwards is a pain in the you-know-what, and c) I always struggle to predict how much load ends up on the database when all services are up and running. Having a serverless db solves all these problems for me and I have used them extensively on AWS, so I went to look for the Azure replacement. But where AWS offers you two open source flavours (Postgres and MySql compatible), Microsoft offers … Microsoft SQL Server. Thats it. You can get a static instance for Postgres and MySQL no problem, but not in a serverless environment. If I ever feel the need to migrate to a fixed instance for cost reasons, I’ll have to stick with MSSQL (which is, by the way, extremely expensive compared to a fixed postgres instance: At the time of writing, a Gen5 4CPU, 20GB Postgres instance goes for 0.352€/hour, while a Gen5 4CPU 20.4GB MSSQL instances will set you back 0.91€/hour).

This was the first time EEE came back into my mind. Shortly thereafter, I stumbled over “stages” for Azure Functions. This is, again, a really thoughtful addition to the service which allows you to deploy your Function code directly into multiple deployment slots like “dev”, “staging” and “production”. The code in these instances can also be switched at will, f.e. you can test you changes and staging and swap this instance over to the production slot with the additional benefit that your application is already “hot”, caches prewarmed etc. A great feature, right? Though luck, you cannot use it if you run your Function code in a serverless Linux environment. You can do so when running in a Windows environment, even when running on a fixed Linux instance, but not on Linux serverless (or “consumption”, as they call it).


Why is that, when the technology is in place for windows, and linux, even serverless environments? Just to make it slightly more inconvenient to use a linux environment for your function. Just as it slightly more inconvenient to use an open source database. Sure, you can use all their development tooling on a linux machine without a hassle, it even is open source for the most part, but in the cloud, where the money is and your business thrives or dies, you can feel the enterprise creep.

Would I recommend it?

So, taking into account all of these things, good and bad, would I recommend Azure? Would I, personally, with my current knowledge, prefer it over AWS?

The thing is: I’d love to hate it. I really do. But Azure continues to feel like the better platform from a UX perspective. It’s obvious that someone paid close attention to all the annoying things on AWS and set out to fix them.

To get back to the question of recommending Azure. I think it basically comes down to whether you think that you can stop Microsoft’s proprietary software from seeping too deep into your stack. Because yes, using a cloud platform in any form always comes with some degree of vendor lock-in, but when the foundation of it is free and open software, you are always able to migrate to another platform or host some services yourself if you like. Sure, this will require a lot of work, but if your business model depends on it, or the need for it is big enough, e.g. when prices increase, terms of services change, or the service you use just develops into a direction which makes it unsustainable to use it further, the possibility exists. Image that Azure stops supporting Linux one day because they think they can take back the server market? Or decide that they can increase licence cost for MSSQL tenfold?

See also