Without Dependency Injection (DI), you would create these objects manually in every function. That quickly becomes messy.
Dependency Injection solves this by:
creating and managing these services for you,
giving them to your function automatically,
making your code easier to test and maintain.
1. Two ways of running Azure Functions
It’s important to know there are two models for .NET Azure Functions:
In-process model (old way)
Functions run inside the same process as the Azure Functions runtime.
Uses a Startup
class for DI.
Still supported, but will retire in 2026.
Isolated worker model (new way, recommended)
Functions run in their own process.
Uses normal .NET Host
and Program.cs
for DI (just like ASP.NET Core).
More flexible and future-proof.
2. Setting up Dependency Injection in the In-Process Model
Step 1. Add required NuGet packages
dotnet add package Microsoft.Azure.Functions.Extensions
dotnet add package Microsoft.NET.Sdk.Functions
Step 2. Create a Startup
class
This tells Azure Functions how to register your services:
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(MyApp.Startup))]
namespace MyApp
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
// Register HttpClient (best practice)
builder.Services.AddHttpClient();
// Register custom service
builder.Services.AddSingleton<IMyService, MyService>();
// Bind configuration section to options
builder.Services.AddOptions<MyOptions>()
.Configure<IConfiguration>((opts, config) =>
{
config.GetSection("MyOptions").Bind(opts);
});
}
}
}
Note
Singleton
= one instance for the whole app
Scoped
= one instance per function execution
Transient
= new instance every time it’s requested
Step 3. Inject your service into a Function
public class MyHttpTrigger
{
private readonly IMyService _myService;
public MyHttpTrigger(IMyService myService)
{
_myService = myService;
}
[FunctionName("MyHttpTrigger")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req,
ILogger log)
{
var result = await _myService.GetDataAsync();
return new OkObjectResult(result);
}
}
3. Setting up Dependency Injection in the Isolated Worker Model (Recommended)
Step 1. Create a new project (isolated worker)
func init MyIsolatedFuncApp --worker-runtime dotnet-isolated
Step 2. Add packages
dotnet add package Microsoft.Azure.Functions.Worker
dotnet add package Microsoft.Azure.Functions.Worker.Sdk
Step 3. Register services in Program.cs
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
var builder = FunctionsApplication.CreateBuilder(args);
// Register custom service
builder.Services.AddSingleton<IMyService, MyService>();
// Register HttpClient
builder.Services.AddHttpClient();
// Register EF Core DbContext factory (optional)
builder.Services.AddDbContextFactory<MyDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// Register options from settings
builder.Services.Configure<MyOptions>(builder.Configuration.GetSection("MyOptions"));
var app = builder.Build();
app.Run();
Step 4. Use the service in a function
public class MyHttpFunction
{
private readonly IMyService _myService;
public MyHttpFunction(IMyService myService)
{
_myService = myService;
}
[Function("MyHttpFunction")]
public async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req)
{
var result = await _myService.GetDataAsync();
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync(result);
return response;
}
}
Conclusion
Dependency Injection makes Azure Functions cleaner, testable, and future-ready. Use the in-process model only if you must, but for all new apps, prefer the isolated worker model to get the full benefits of modern .NET and long-term support. Keep functions lean—let DI handle your services.