We recently performed a general cloud evaluation between AWS and Azure to decide which cloud we would use for the foreseeable future. A big part of the evaluation was serverless capabilities specifically AWS Lambda vs Azure Functions. We built a similar POC in each cloud using a serverless architecture and learned a lot. So I thought it would be good to summarize our findings in blog post form both for posterity and to share with others.

Serverless Architectures

I’ll be the first to admit we are still in the early days of serverless. That being said many developers have built production systems with them and are using them with great success. All cloud providers are still innovating in this area to make serverless even more productive and capable. The term “serverless” itself is even evolving with some critics arguing it is misleading and prefer “less-server” instead. As I type this post I have red squigglies under each instance of the term serverless because the term is so new many spell checkers haven’t caught up.

Serverless doesn’t mean there aren’t servers, it means you don’t have to worry about them as a developer. Instead the server/OS is managed by the cloud provider.

All that said, this is an area that is moving VERY quickly so its important to stay up-to-date. The information in this blog post for example, will likely be out-of-date or at the very least missing new information by the end of the year. So be mindful of blog post dates while doing your research.

Similarities

Both AWS Lambda and Azure Functions provide a mechanism to execute code (functions) without setting up a server. They both support creating/editing functions purely from their respective portals or you can develop functions in Visual Studio and deploy to the cloud. Both offer numerous triggers to kickoff the function, for example document creation, queue messages, cloud events, etc. Both support the use of environment variables for configuration management. Basic monitoring of functions is also provided by both.

Overall the two offerings do provide the same core capabilities you would expect but there are differences too.

General Differences

Timeout (Azure +1 point)

AWS Lamba allows a maximum of 5 minutes for functions to run. Azure defaults to a 5 minute timeout but can be configured to allow up to 10 minutes on the consumption-based hosting option. Azure Functions hosted via App Services (more on this below) however do not have a timeout. (Thanks for the reminder TimAus!)

Monitoring (Azure +1 point)

AWS Lambda provides high-level monitoring of functions with 6 basic metrics covering: invocations, duration, throttling and errors. In addition to these basic metrics, Azure Functions supports detailed function code monitoring through Application Insights with a single checkbox. AWS XRay can be configured for AWS Lambda to provide deeper monitoring which isn’t hard to setup but is far more work than a single checkbox.

Performance (AWS +1 point)

Per the excellent performance analysis done by James Randall, recent improvements have made the Azure Function runtime much more performant but still doesn’t match AWS Lamba in performance. Previously, Azure Functions were almost unusable for most production use cases but its much better now and the team is still working on improving it further. Further improvements will likely come with the v2 runtime which is likely to release before the end of the year.

Check out James’ blog posts for more details:

https://www.azurefromthetrenches.com/azure-functions-vs-aws-lambda-scaling-face-off/s

https://www.azurefromthetrenches.com/azure-functions-significant-improvements-in-http-trigger-scaling/

https://www.azurefromthetrenches.com/azure-functions-v2-preview-performance-issues-net-core-standard/

Regarding C# performance on AWS Lamba, compared to other supported languages, it is considerably faster than all other options. Checkout Yun Zhi Lin’s excellent article on this topic for more info (Thanks for the tip uscbmrf).

https://read.acloud.guru/comparing-aws-lambda-performance-of-node-js-python-java-c-and-go-29c1163c2581

Debugging (Azure +1 point)

AWS Lambda does have the SAM CLI tool which allows you to run/test Lambda functions locally. Although C# is not listed on the official supported runtimes list. I did find some documentation that indicates you can run .NET Core functions in SAM, but I have not tested this and can’t verify it works yet.

Visual Studio provides the expected, dead simple local F5 debugging out of the box for Azure Functions. In addition you can debug functions remotely in Azure which is really cool!

Azure Function Bindings (Azure +1 point)

One of the most exciting features I saw on either cloud provider was the triggers and bindings offered by Azure Functions. These bindings can be defined declaratively in the function.json file or using parameter attributes in the code. There are three binding types: triggers, input bindings or output bindings.

https://docs.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings

Each binding supports a list of parameter types that can be used to represent the binding. This was the really cool part. For example, the blob storage binding can be represented with a Stream, string, Byte[], ICloudBlob and many more:

https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-blob#trigger—usage

This allows the developer to choose a binding and then parameter type that best fits their use case or development style. I think this is a key differentiator for Azure Functions that Microsoft will continue to innovate and bring value to developers with.

.NET Core 2.1 Support (AWS +1 point)

One of the most surprising differences I found was that Azure Functions still doesn’t support .NET Core (any version) with a GoLive license yet. They announced the v2 Azure Functions runtime last September (2017) and still don’t have an official release date. Microsoft seems to indicate the v2 runtime should be complete before the end of the calendar year but no hard dates yet.

AWS however, announced support for .NET Core in January of 2018.

‘’

We performed our POC against the v2 runtime and were able to get it working with .NET Core but we can’t use any of it in production until Microsoft provides a GoLive license.

Hosting (Azure +1 point)

Azure provides two ways to host Azure Functions, their consumption model (similar to AWS Lamba) and via App Service hosting. Each is useful in different use cases. If you expect your function to always be running it may actually be cheaper to host using the App Service:

https://docs.microsoft.com/en-us/azure/azure-functions/functions-scale

The Azure Functions runtime is also open source and can be run via containers which opens other possibilities for running Functions on premises or in other clouds.

https://carlos.mendible.com/2017/12/28/run-a-precomplied-net-core-azure-function-in-a-container/

Azure Stack also supports running Azure Functions.

This breadth of options is really nice. This is a true differentiators and allows you to run Azure Functions wherever you want.

Conclusion

Everything else being equal I think Azure Functions wins even though the v2 runtime isn’t out yet. The monitoring, debugging, hosting and binding options put it over the top for me personally. You could write your functions using the Full .NET framework today using all the great features of Azure Functions and then easily migrate to Core and the v2 runtime when it is released.

However everything else is hardly ever equal. In our case, the development team had more experience with AWS and we would have had to migrate a bunch of existing code from AWS to Azure. So we decided to stay in AWS and use Lamba for now.

Although, we are keeping an eye on the v2 Runtime and are working hard to write our functions as cloud-agnostic as we can (another blog post to come on this) so that we have the option to migrate in the future.

This was our experience but what do you think? Please take a few minutes to share your experience, ask questions and continue the conversation in the comments below.

Happy (serverless) coding!