Don’t use Azure Functions as a web application

Edit on GitHub

I know, I know. That title is probably a bit too harsh and opinionated. But it got your attention, right?

A friend of mine this week asked me whether they could use middleware in their HTTP-triggered Azure Functions, ideally even the same ones they use in ASP.NET Core applications. After all, the SDK comes with HTTP triggers that seem to use the same infrastructure, right?

My immediate response was “whyyyyyy?!?”. And in this blog post, I’ll try to explain.

via GIPHY

Yeah, but your scientists were so preoccupied with whether or not they could, they didn’t stop to think if they should. - Dr. Ian Malcolm

Many folks out there, including some of the official information, see Azure Functions as a convenient way to quickly deploy a simple API. And that’s somewhat correct, and often perfectly fine for a lot cases

Except, if you need full-blown middleware and the options the ASP.NET Core web pipeline offers, maybe… Well, maybe ASP.NET Core is the choice for those.

Azure Functions are not a web API-building-platform as such. A function gets triggered and receives input, runs some logic, and provides output. Functions can be chained into a pipeline that passes around messages. They can scale based on capacity needed to handle those incoming messages. And that, I think, is the key.

Azure Functions provide a reactive orchestrator. They handle messages.

Based on various triggers, such as queues, storage, events coming from another service, they set logic in motion. In that sense, using an HTTP trigger does not mean you are building a full-blown web API. The HttpTrigger is one of many triggers that provides an incoming message to your function. An HttpRequestMessage, with lots of properties such as headers, query string parameters and so on.

At its core, that HttpRequestMessage is not different from handling a BlobUpdatedEvent from storage. Granted, the latter is a less complex message, but they are the same. The only difference is that they look like an explicit call to an endpoint.

Functions should do one thing (or realistically, as few things as possible).

Using Azure Functions and HTTP triggers to build a simple API? Go for it! It’s perfectly fine to handle a couple of events that may originate from your Vue, React or Angular front-end.

Shoehorning a full ASP.NET Core into Azure Functions? Well, if you need the full ASP.NET Core stack for the job, why not use it? If you need only parts, put API management, CloudFlare or nginx in front of your HTTP-triggered function.

HTTP is just another type of message that triggers your function logic.

Leave a Comment

avatar

15 responses

  1. Avatar for teodor
    teodor January 28th, 2020

    Given the cost of the alternatives on Azure (VM or App Services or hosted Containers), functions can be a much cheaper alternative for a small set of RESTful APIs. App Services are quite expensive compared to other non-azure alternatives.

  2. Avatar for Maarten Balliauw
    Maarten Balliauw January 29th, 2020

    Completely agree. The nuance is in your comment:

    functions can be a much cheaper alternative for a small set of RESTful APIs

    Don’t shoehorn a full-blown API into functions. But a small set of API’s is probably fine. In fact, this comment was posted through such small API hosted as a function.

  3. Avatar for Dirk
    Dirk February 4th, 2020

    I completely agree with you. When I think of Azure Functions, I think of code that is responsible for one thing only. Wearing my “SOLID” hat here I guess, but bloating Azure Functions seem smelly.

  4. Avatar for Dan Mc
    Dan Mc March 4th, 2020

    I’ve read this article 3 or 4 times to try and see the bit where you give a compelling reason as to why functions can’t be used as a full API. I wholeheartedly agree ‘things’ should do one thing (not least functions), but single responsibility principle isn’t mutually exclusive to API design.

    Your article just says “don’t”, not sure I’m bothered enough about you “yelling” to avoid using functions for this.

  5. Avatar for Maarten Balliauw
    Maarten Balliauw March 6th, 2020

    I’m perfectly fine with using Azure Functions and HTTP triggers to build a simple API underpinning your Vue, React or Angular front-end.

    However, I’ve seen projects where people are shoehorning full-blown ASP.NET Core into Azure Functions. If you need those, maybe just using them directly will be better and save headaches in the longer run.

    Example I’ve come across recently was a project that had 600 functions in one function app, doing all kinds of middleware things and essentially hosting ASP.NET Core. Hell to maintain, as everything was linked together by REST calls to have one function call another one. All functions seemed to belong together, and seemed a much better fit for a traditional ASP.NET Core app in terms of maintainability.

    “But microservices! We can scale functions independently!” Great. But each deployment of that 600-function-app would bring all functions down and start all of them again. What’s the benefit of using Azure Functions then?

    In summary: this post is not about NOT using Azure Functions for HTTP API’s. It’s about not just jumping on them for applications that would be better suited to be built with other technologies. Or as with many things: “it depends, use the right tool for the right job”. And if the right tool is Azure Functions, by all means go for it.

  6. Avatar for Homer
    Homer March 17th, 2020

    I agree with Dan Mc, no really good reason is given except this horrible example you wrote as a comment on 06 March. People are misusing so many frameworks and technologies, so such “worst cases” are irrelevant for suck discussion

  7. Avatar for Maarten Balliauw
    Maarten Balliauw March 26th, 2020

    @Homer It is what it is. Let me reverse your comment: what would be a compelling reason to use HTTP-triggered functions for a full-blown API surface?

    The answer to that question could be describing a scenario where the choice for HTTP-triggered functions makes perfect sense to build a full-blown API. And that would mean there was thought put in, and there was a compelling reason. If there’s tremendous value, whether on the technological side or the process side, it means you’ve considered alternatives and weighed options. Go for it, in such case!

    Open to examples on either side of that spectrum, it could only help those who land here.

  8. Avatar for pamnani
    pamnani April 6th, 2020

    @Maarten.. Example you wrote as a comment on 06 March, deployment will bring down all function down…isn’t depends on deployment pattern and can be avoided with using the deployment slot.

    One thing which I see if more than 1k request hits at the same time to micro service build using 10 different function (APIs) and then to handle integration among function, security, network communication be bit challenge specifically when web app consist of 100 micro services or more.

  9. Avatar for The Algorist
    The Algorist April 16th, 2020

    What I am reading is this: “Don’t create a monolithic azure function group that does everything.” I would hope that no one is doing that, but I know people are doing that because I’ve seen it. I’m not certain that I see a compelling reason, in this article, as to why you shouldn’t do that except it is against best practices. It may sound dirty, but I almost feel like it is reasonable to say that moving an api from a ASP.Net core web api to an azure function is a step in the right direction because it allows you to run your code in a serverless environment.

    Thanks for the article.

  10. Avatar for Ian Kemp
    Ian Kemp May 7th, 2020

    You’ve told us to use the right tool for the job, but you haven’t told us how or why to choose which is “right”, i.e. what should be evaluated when trying to choose between these options.

    Off the top of my head, Functions give us autoscaling and are cheaper, but miss out on a lot of aspects of ASP.NET Core (pipeline, middleware). Web API requires App Services which is more expensive and scaling has to be setup manually, but is far more flexible.

    It seems to me that unless your primary concern is price, it always makes sense to go with standard Web API. What else am I missing?

  11. Avatar for Maarten Balliauw
    Maarten Balliauw May 13th, 2020

    It all depends. Generally speaking, functions are perfect for event-driven work. Such event can be a blob being created, a message on a queue, a timer that fires, and yes, even an incoming HTTP request.

    If you need the full-blown ASP.NET Core feature set, then it starts getting murky. It’s possible to use many of those features in Azure Functions, but then the question is whether it’s the best fit for those cases. It can be, but this is where I wanted to go with this post: use your judgement, ideally based on experimentation or experience, and not blindly pick functions for these. They can be a good fit still, but the keyword(s) are “use your judgement”.

  12. Avatar for Pavlo P
    Pavlo P June 2nd, 2020

    Where is the benefit to have many functions instances opposite to monolith? If we have so good scaling, should we care? And yes, I am still sure that middle size monolith is better that hundreds of instances without assigned devops to manage them.

    So only argument against functions as web api - no pipelines, middleware and some other stuff we can’t remember? Pipelines and middleware can be written in less that 100 rows of code, so is it a problem? Do you see any other?

    Probably performance may straggle since with functions you will have relatively small one instance size (RAM, CPU) and warm up for complicated API may take a while.

  13. Avatar for Man Singh
    Man Singh June 26th, 2020

    If you are thinking of using Azure Functions purely to save costs using a consumption plan, please be aware you will lose features such as VNET integration, which is only possible in premium plan.

  14. Avatar for Manish Jain
    Manish Jain September 6th, 2020

    I agree with the article. @Dan Mc and @Homer If you are looking for a reason to NOT use Azure functions (AF) in HTTP/Web scenarios where client’s are constantly hitting the APIs: One simple word: cold start (in non premium plans). If AF is not ‘always on’ then clients would be waiting forever to boot up and run the function. This is not practical for many applications. It’s not right for companies to advertise/mislead ‘serverless’ buzzword for everything. If you are using AF with premium plan/always on then its not truly a serverless function rather than twisted Web API. In this case you are paying the same for hosting AF (as Web API) then why not use Web API that is more feature rich.

  15. Avatar for Christian
    Christian April 12th, 2021

    Agree and disagree. Let me explain. Mostly you should at every level choose to do server less functions. What server less functions are not good at inherently are providing the actual core code base especially in the .net core framework.

    Javascript can employ this issue as well. For example When doing an http trigger you have only access to the functions https class. So many times things you’re used to doing in express or net core natively you’re limited to that class.

    Again, if you want to protect a route and authorize a route you’re going find that you become stuck in ways that won’t allow you to just install a package or library and use it like a native server code base.

    You’re not going to have an in depth controller system in a function.

    Also memory cache and state is not really available in a function but signalr and redis are available to you. So… There’s usually a way.

    Remeber though, It’s gotta be done the functions way and additions thereafter. But most of the time it’s ok and you still can do most of what you need accomplished.

    So for more complicated and custom code bases I agree it’s not maybe the path you want.

    However, if you can do it in a function you should do it in a function.

    Function first design.

    Go from there. You’ll be surprised. And cold starts aren’t an issue you can have full time server functions.