Azure Functions vs. AWS Lambdas: A .NET Developer's Perspective

Have you gotten around to trying this “serverless” stuff out?

I recently had to scratch my own itch and put together a couple small utilities, one with an AWS Lambda, and the other with an Azure Function.

Have you wondered if one was better than the other?

The experiences were… similar, but also quite different, and thus I share a .NET developer’s perspective of each.

Before I start, keep in mind that whilst building both of these utilities, my mindset was “let’s get this thing live as fast as possible”, and not “let’s do precision research on the most effective way to implement this using each platforms recommended tooling and workflow”.

Nowadays I tend to try and get something working first, and then refactor it into something more elegant after.

With that in mind, this article reflects my opinion as a first time user just getting started, with a bias of being heavily engulfed in the .NET world and with quite a bit of prior Azure experience (I’ve built out an entire Azure cloud infrastructure from scratch.)

In contrast this was the first time touching AWS other than migrating personal files from Dropbox to an S3 bucket (easy way to save 10 bucks a month!)

Building an AWS Lambda

The idea of using an AWS Lambda came to me when I was stubbornly resistant to putting any javascript on this very blog. Not because I don’t like javascript, but simply because the blog started out as pure static html and css and the minimalist in me wanted to keep it that way.

I needed an elegant way to allow folks on my email list to be able to sign up for other gizmos on my site even if they had already signed up for something else.

My email provider, Mailchimp, would require you to check off boxes for what they wanted, which was a shit experience.

I could have called their API via some javascript, but rather than shattering my holy static site purism, I decided to have my email sign-up form simply POST itself and handle the work on a server. Since I had recently deallocated my personal server droplet, I thought hey, a serverless function would be perfect!

Being the first time I dipped my toes into serverless, I found the experience very liberating.

Once you create an AWS developer account and navigate around the grid of seemingly hundreds of oddly named AWS resource offerings displayed in Amazon’s classic ugly font against a dull gray background, it’s fairly seamless setting up a basic Lambda.

The Lambda creation workflow guides you along choosing a language and platform, sets you up with an in-browser text editor, and presents an interface similar to one of those middle school programming languages where you link different components together for input and output.

The AWS Lambda editor

It’s ugly, and it gets more confusing as you add additional complexities, but it works.

For this project, I chose NodeJS as the framework, since I had recently enjoyed how its expansive package ecosystem paired with javascript’s loose typing allowed me to fumble together guilt-free utilities at lightning speed.

Now, I’m willing to bet there are nicer deployment experiences than what I used, but combining NodeJS with the in-browser editor was not ideal.

If you haven’t used NodeJS before, when you want to pull in an outside library like you would with NuGet in the .NET world, you have to declare its use first and then npm (the package manager) pulls in all of the library’s raw code right within your project into a folder called node_modules.

This process is mostly automatic if you have your local dev environment set up for it, but it doesn’t work in the AWS Lambda in-browser editor. The only solution at the time of building it was to instead build the majority of the utility locally using VS Code, then uploading it and the node_modules folder back into AWS.

Like I said, there are probably better ways, but this was my experience trying to build at relatively fast pace.

Once I had the utility doing what I needed, which was essentially just calling a few Mailchimp API endpoints, I just had to configure the function so it could actually be executed via an HTTP POST.

You can see the code here if you’re curious. It ain’t perfect but it gets the job done!

This was another knock against AWS. Although I will say, it was still a good experience, but you’ll see why I say this when we get to the Azure side of things.

In order to set up the endpoint, you had to provision another kind of AWS resource called an API Gateway.

An API Gateway allows you to set up the URL format, authentication scheme, and available HTTP methods that you can slap in front of any other AWS resource as the first line of interaction from the public internet into your cloud resources.

Still easy in the grande scheme of software development and deployment, but again, Amazon could definitely work on the user experience design.

I did have some difficulty creating an authorization scheme so that only my website could call it. Compared to Azure Functions, it was rather confusing to set up a token that could be used. Eventually I figured it out, but it’s worth noting that it wasn’t seamless.

Once the API Gateway was up and running, I was good to go.

At the time of this article being written, this Lambda has been serving this site without any errors for several months at no cost to me.

Despite the quirks with uploading javascript files and vanilla Amazon design, I found this to be very gratifying.

Both AWS and Azure offer these services with 1 million free executions per month, so if you’re creating something with less traffic than that, it’s pretty amazing to be able to plug into that computational power for almost no cost.

Pros

Integrates well with other AWS offerings.

If you’re already an AWS user, you might as well stay within the confines. Lambdas are built with the expectation that you will connect them to your other AWS resources, and from my experience, both AWS and Azure are similar enough that there wouldn’t be a compelling reason to exit your existing cloud.

If you prefer command-line tooling, or are a linux/java dev, you might enjoy AWS Lamdas more.

I believe Amazon skimps on their UI because they offer robust command-line tooling. I’ve only used a bit of it in my experience, but have heard from others that it is great. I encourage you to explore that on your own and report back.

Cons

The user experience is lacking.

I find Amazon to be lacking in design in just about ALL of their products. Maybe it’s just me but I find myself wondering how anyone can navigate around their sites if they aren’t already a keen technologist. But hey, money bags Bezos obviously isn’t hurting from it.

Setting up the API Gateway was clunky.

This was similar to above, a user experience problem. A bit confusing setting up an authorization scheme.

Manually uploading the source files wasn’t pleasant.

It’s likely AWS has a better deployment method, but this was the straightforward solution using the in-browser editor.

For all I know, there might be Visual Studio tooling that would have made it easier, but again, it wasn’t obvious, and you’ll see below how drastically different this experience was whilst already being in the Microsoft landscape as a .NET developer.

Azure Functions

My introduction to Azure Functions was very recent, about one week before writing this article, so it’s fresh on my mind.

A friend of mine uses a shopping cart tool that doesn’t provide a public API to its users, but instead offers a push notification event option. So you can’t them ask “how many sales have I made for this product?”, but you can listen for sales events, collect that data into your own database, and then you’ll be able to answer that question for yourself.

Handling notifications from an external service is a perfect use case for a serverless utility, so this was my hell yes moment. Time to try out new toys!

I had two big advantages coming into this, one that I had already used Lambdas, and two, that I have essentially built an Azure cloud infrastructure from the ground up, so it was all familiar territory. First I followed the Getting Started documentation to familiarize myself with the Portal based deployment which is analogous to the AWS in-browser text editor.

What I noticed right away, to contrast from AWS, is that two of the main trouble spots I had with AWS were taken care of by default in Azure. Simply selecting the Webhook + API function template option from the initial wizard automatically created the API endpoint for calling the function, along with a client authentication token.

The Azure Function initial creation wizard

In the prior step you could also choose from a number of deployment methods including Visual Studio, VS Code, Portal editor, and command-line.

Because the functionality of this utility was going to be rather complex (parsing an incoming notification and calling the Google Spreadsheets API to fill a table), I decided to try out the Visual Studio deployment option rather than the browser editor.

For this, I upgraded Visual Studio 2017 to 2019 (yay more new toys!) and used the included template for an Azure Function.

This was dope.

It sets you up with a local dev environment to test on, and get access to the usual one-click publishing feature that lets you push everything right into Azure. One thing that stood out to me as pretty nifty was the local to remote app settings UI.

Your app settings are encrypted locally, and when deployed, you could see a side-by-side comparison of local vs. remote settings values where you could edit right within Visual Studio.

The Azure Function app settings publish dialog

It should be expected, really, but this is where it helps to already be a .NET and Visual Studio user. The experience of building this (in .NET Core by the way), testing it, and deploying it was seamless. All the way from finding up-to-date documentation and guides, to having a live function that processes those shopping cart events.

NOTE: This code is currently in a private repository, but I will be publishing a video (initially to folks on my email list) where I’ll be refactoring this function. You can add your email below to get in on that before it’s public.

Get an early-bird look at my Refactoring an Azure Function video post

It was also nice that the function itself was very similar to an ASP.NET Core controller action.

Pros

As a .NET Developer, Azure’s integration with Visual Studio made the entire experience far more delightful.

You can choose to build and deploy from the Azure Portal, Visual Studio, VS Code, or command line, and each option came with clear documentation and easy publishing steps.

HTTP trigger endpoints and authentication configured by default, stupidly easy.

The most common ways you will want to set up your function are configured by default. There aren’t additional resources you need to learn about or set up.

Strong documentation

Microsoft has been putting a ton of effort in to create clear and up-to-date documentation and the effort is obvious in this area.

Cons

I’m reaching here, but if I were to knock something it would be that sometimes it’s not clear what things cost.

For example, I understood that 1-million executions of the function would be free, but in order to have the function live, you also need a storage account. It might be nice to display dollar values in-and-around the deployment screens.

Both Visual Studio and Azure Portal do a nice job at auto-populating everything you need, so it would be cool if it also made it clear what the total monthly cost estimate is. I noticed that my current Azure storage account and logging resource will bill me about $0.12 per month as it currently stands.

Final Thoughts

Coming from my current job where we are still deploying manually via installer UIs on virtual machines, this whole experience with serverless functions was an incredible delight. That’s with both AWS and Azure.

It brought me back to that classic experience of my childhood when I got boosts of self-esteem from writing a bit of HTML and CSS and seeing it magically create something in the browser instantly. This was that experience all over again except with actual computation on a live HTTP endpoint over the web.

The fact that we can build these micro apps at little to no cost is also a real game-changer, especially as an entrepreneur. It opens up an entirely new canvas to create upon.

I encourage you to try both AWS Lamdbas and Azure Functions, since I found them to be similar enough that your own personal preferences will be more important than my opinion. With that said, I believe you will find a much more seamless and fluid experience by using Visual Studio with Azure Functions. All the futzing around I had to do with AWS was taken care of by default in Azure.

As you might expect, it’s a lot like using a Mac if you are an iPhone user. You benefit greatly by staying within the walls of your ecosystem.