yesman
yesman

Reputation: 7838

Is dependency injection and Mediatr in combination with Azure Functions inefficient?

I'm in early steps on my Azure journey. The way I understand functions is that they're a serverless solution that is only run when actually needed. After performing their logic they "shut down" again. This is cheaper compared to something like an App Service, which is always running, even if there's no requests.

My current situation: I have a solution set up in a DDD design similar to Microsoft's eshoponcontainers solution. I have a webapi project that only has super thin controllers, that simply pass their input to Mediatr, which passes it to different projects for validation and business logic. All my controller methods look like this:

[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetById(string id)
{
    // Mediator instantiated via DI in the controller constructor
    var result = await Mediator.Send(new GetByIdQuery { Id = id });
    return Ok(result);
}

It's trivial for me to remove this webapi project, and replace it with an Azure Functions project that also takes input from an HTTP Trigger and pass it to Mediatr. My dependency injection stuff is set up in a different project, independent from webapi so that's easily inserted in my Azure Functions project as well. All my functions look like this:

public class GetId
{
    private readonly IMediator _mediator;

    public GetId(IMediator mediator)
    {
        _mediator = mediator;
    }

    [FunctionName("GetById")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] string id,
        ILogger log)
    {
        var result = await _mediator.Send(new GetByIdQuery { AgreementId = id });
        return new OkObjectResult(result);
    }
}

But isn't this terrible from a cost perspective? Based on my limited understanding, every time the Azure Function is started, it will create my substantial DI container all over again. This means I'm paying a lot for CPU time that's doing DI setup, instead of my actual business logic. Or am I missing something?

Upvotes: 5

Views: 2621

Answers (1)

Leaving aside the web API vs Azure Functions discussion, what you're doing is rather bizarre: accepting a message so that you can use Mediatr to manually fire an event based on that message's contents.

Azure already has built-in functionality for exactly this: Event Grid, Event Hub, or Service Bus. Create one of these resources, publish events/messages to them instead of to a web API/Azure Functions, and replace your Mediatr event listeners with Event Grid/Event Hub/Service Bus listeners. Then you don't need a web API or Azure Functions at all.

In regards to the actual question, there are many concerns that come with Azure Functions - inability to use ASP.NET Core middleware is a big one. You might save on resource usage, but honestly Azure is so cheap that such a saving is likely to not be worth it. (I suggest you look at the actual pricing, as opposed to assuming that Azure Functions will save you money simply because it's not always-on.) And no, DI container construction doesn't cost much CPU at all - if it does, you have bigger architectural problems.

There are always tradeoffs, and nothing is free.

Upvotes: 3

Related Questions