Whenever I meet clients and give a talk about Azure Functions, they are immediately interested in replacing their existing Web API features with Azure Functions. In this post, I’d like to discuss:

  • Can Azure Functions replace Web API?
  • Is it worth doing?

It would be a good idea to have a read through this article, Serverless Architectures, before starting.

HTTP Trigger Function == Web API Action

One of characteristics of Serverless Architecture is “event-driven”. In other words, all functions written in Azure Functions are triggered by events. Those events of course include HTTP requests. From this HTTP request point of view, both HTTP trigger function and Web API action work exactly the same way. Let’s compare both codes to each other:

How do both look like? They look pretty similar to each other. Both take an HTTP request, process it and return a response. Therefore, with minor modification, it seems that Web API can be easily migrated to Azure Functions.

HTTP Trigger Function != Web API Action

However, life is not easy. There are some major differences we should know before migration:

Functions are always static methods

Even though Azure Functions are extensions of Azure WebJobs, each function has a static modifier by design, unlike Azure WebJobs can be without the static modifier.
Actions of Web API, by the way, don’t have the static modifier. This results in a significant architectural change during the migration, especially with dependency injection (DI). We will touch it later.

Functions always receive HttpRequestMessage instance as a parameter

Within the HTTP request/response pipeline, a Web API controller internally creates an HttpContext instance to handle data like headers, cookies, sessions, querystrings and request body (of course querystrings and request body can be handled in a different way). The HttpContext instance works as an internal property so any action can directly access to it. As a result, each action only passes necessary details as its parameters.
On the other hand, each function takes a different HTTP request/response pipeline from Web API, which passes the HttpRequestMessage instance to the function as a parameter. The HttpRequestMessage instance only handles headers, querystrings and request body. It doesn’t look after cookies or sessions. This is the huge difference between Web API and Azure Functions in terms of stateless.

Functions define HTTP verbs and routes in function.json

In Web API, we put some decorators like HttpGet, HttpPost, HttpPut, HttpPatch and HttpDelete on each action to declare which HTTP verbs take which action, by combining with the Route decorator.
On the other hand, each function has a definition of HTTP verbs and routes on function.json. With this definition, different functions having the same route URI can handle requests based on HTTP verbs.

Functions define base endpoint URI in host.json

Other than the host part of URI, eg) https://api.myservice.com, the base URI is usually defined on the controller level of Web API by adding the Route decorator. This is dead simple.
However, as there’s no controller on Azure Functions, it is defined in host.json. Default value is api, but we can remove or redefine to others by modifying host.json.

While function.json can be managed at the function level through GUI or editor, unfortunately it’s not possible to edit host.json directly in the function app. There’s a workaround using Azure App Service Editor to modify host.json, by the way.

Functions should consider service locator pattern for dependency management

There are many good IoC container libraries for Web API to manage dependencies. However, we have already discussed this in my previous post, Managing Dependencies in Azure Functions, that Service Locator Pattern should be considered for DI in Azure Functions and actually this is the only way to deal with dependencies for now. This is because every Azure Function has the static modifier which prevents us from using the same way as the one in Web API.

We know different opinions against service locator patterns for Azure Functions exist out there, but this is beyond our topic, so we will discuss it later in another post.

Is Azure Functions over Web API Beneficial?

So far, we have discussed what are same and what are different between Web API and Azure Functions HTTP Trigger. Back to the initial question, is it really worth migrating Web API to Azure Functions? How does your situation fall under any of below?

  • My Web API is designed for microservices architecture: Then it’s good to go for migration to Azure Functions.
  • My Web API takes long for response: Then consider Azure Functions using empty instance in App Service Plan because it costs nothing more. Consumption Plan (or Dynamic Service Plan) would cost too much in this case.
  • My Web API is refactored to use queues: Then calculate the price carefully, not only price for Azure Functions but also price for Azure Service Bus Queue/Topic and Azure Storage Queue. In addition to this, check the number of executions as each Web API is refactored to call one Http Trigger function plus at least one Queue Trigger function (two executions in total, at least). Based on the calculations, we can make a decision to stay or move.
  • My Web API needs a significant amount of efforts for refactoring: Then it’s better to stay until it’s restructured and suitable for microservices architecture.
  • My Web API is written in ASP.NET Core: Then stay there, do not even think of migration, until Azure Functions support ASP.NET Core.

To sum up, unless your Web API requires a significant amount of refactoring or written in ASP.NET Core, it surely is worth considering migration to Azure Functions. It is much easier to use and cost-effective solution for your Web API.

Category:
Application Development and Integration
Tags:
,

Join the conversation! 22 Comments

  1. Great topic and post Justin. Have you found any difference regarding instance start up (i. e. cold vs warm start) particularly on a Dynamic Plan where you don’t own a PaaS VM Instance?

  2. Great post that I found useful thinking about using an App service or Functions. I’m not familiar with the Web API layer that functions is built on but am with Functions and plan a JS API and serving HTML. Thus my considerations are more about pricing and feature support. Here are a couple of questions
    1) “consider Azure Functions using empty instance in App Service Plan because it costs nothing more”. I don’t get this. as far as I know Functions are Dynamic or classic plan only.
    2) Can you expand on the cookie and stateless point? Can we manage cookies form Functions
    3) Not covered but a FAQ must be using HTTPS with custom domains. How do we do this with Functions? This needed for both APIs and serving HTML etc for Apps using service workers.
    thanks

    • Hi, Steve. Thanks for your comment.
      1) Dynamic Plan has changed its name to Consumption Plan and App Service Plan in my post is, I believe, your “classic” plan. When you create a web app, it must belong to an App Service Plan. Azure Functions is basically a web app so it can belong to App Service Plan. We only pay for the App Service Plan, not individual web apps. Each App Service Plan can contain number of web app instances based on its pricing tier.
      2) I don’t think cookie is possible on Azure Functions. Cookie means stateful, but Azure Functions (and other serverless services from other providers) is stateless so neither cookie nor session can be used. If you want to use cookies from your web app, you should implement API facade (or API proxy) between web UI and Functions.
      3) Azure Functions is basically a web app. So, in order to setup HTTPS with custom domains, simply go to app service settings, find the custom domains blade and SSL certificates blade, and setup custom domains and SSL certificates, like other web apps instances.
      HTH

  3. “My Web API is written in ASP.NET Core: Then stay there, do not even think of migration, until Azure Functions support ASP.NET Core.”
    Why should somebody not migrate to Functions from Core?
    I am currently evaluating on how to bring my on premise ASP.NET Web API to Azure and I am still unsure what suits my needs best. It’s a small solution with like 6 tables and some relations between them. What I need is a REST Api for Xamarin.Forms & WPF frontends with Azure AD authentication that is easy and fast. Currently I have three possible ideas in my head: Azure Functions with DocumentDb for the data, Azure Mobile Services or ASP.NET Core hosted as an Azure Web App. What suits me best?

    • @chris Thanks for your comment.
      That’s simply Azure Functions only supports .NET Framework 4.6 at the moment. We will be able to choose a .NET framework version that suits for our purpose when they support that feature, but not sure when it will be.
      In your scenario, that’s totally up to your decision. I would be tempted using Azure Functions but not quite sure of other factors impacting on the decision.

      • Thank you for your reply.
        Ah sure. I thought there was something more to it.
        Also for Azure Functions I would implement a regular REST client on the frontend that can be generated through Swagger/NSwag, right? On top Mobile App Services are not WPF compatible I think?
        We will also most likely build the backend on the SAP HANA platform for showcase purposes (my employer is a SAP consulting company). If done correctly I could use the same client for both backends. For real production I want to use an Azure based solution, because it integrates way better into the .NET chain, it has unique features I want to use in my solution (Push Notification service, Microsoft Bot Framework) and I want to learn the Azure services for future projects.

      • @Chris Mobile App Service is basically the same as Azure App Service (Web, API and Mobile), so I don’t see any reason this is incompatible with WPF, as long as the WPF app calls web APIs.
        If your company is planning to integrate SAP modules. just have a brief look at Azure Logic Apps, if it fits your needs or not.

  4. Hi Justin. Would I save more cost if I have Azure Functions on App Service Plan rather than Web API on App Service Plan assuming both are using the same codes?

    • @Elvin Thanks for your comment!
      Yes, in most cases, Azure Functions on a Consumption Plan will significantly reduce your running cost as you only pay for the execution numbers and times taken. However, if your API takes a little longer than usual to return responses, then the Consumption Plan wouldn’t be ideal.

      • Thanks, Justin.
        However, I meant Azure Functions on an App Service Plan and not Consumption Plan. So if you have a Web API on the App Service Plan and you can convert it to an Azure Function but still use App Service Plan would you save more on this?

      • @Elvin Running both Web API and Azure Functions on App Service Plan doesn’t make a difference from the cost perspective because both are basically the same web app instance hosted within one App Service Plan.
        We only pay for the App Service Plan, not individual web app instance.

  5. Azure Function don’t support for middleware also.

    • @akodoshado Thanks for your comment!
      You’re right. Azure Functions doesn’t support middleware because we don’t have to care about middleware.

  6. I would just like to add a point here. It’s very easy to make your WebAPI OData Compatible(or at the least, have few of your controllers with OData like queries allowed). If you are using Entity Framework just minor code change would do the trick.
    However, in case of Azure Functions, that’s not easy. You may want to use Azure Functions Proxy to have your URL look better (like /api/products etc.) but OData style query is still difficult.
    I would like to know if somebody has actually tried making OData queries with Azure Functions.

  7. Proper dependency injection & scopes, middlewares, formatters, custom logging, custom authentication, integration testing, singletons management (required with most database drivers)… all of that is either unsupported or a pain to write out of the box in Azure Functions. In my opinion Functions are not yet suited for replacing Web Api in an enterprise project needing more than a few webhooks with very irregular trafic and low execution times.

  8. Hello Justin,
    Nice article.
    A Web Api would also differentiate from an HTTP Trigger function on a Dynamic Plan by providing AlwaysOn and minimising cold starts.

  9. Hello, it would be nice if you could redo the comparison or update your post as azure functions now includes many more features. Thx

Comments are closed.