Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Important
Support for the in-process model ends on November 10, 2026. Migrate your apps to the isolated worker model by following the instructions in this article.
This article walks you through the process of safely migrating your .NET function app from the in-process model to the isolated worker model. To learn about the high-level differences between these models, see the execution mode comparison.
This guide assumes that your app is running on version 4.x of the Functions runtime. If not, use the following guides to upgrade your host version. These host-version migration guides also help you migrate to the isolated worker model as you work through them.
- Migrate apps from Azure Functions version 2.x and 3.x to version 4.x
- Migrate apps from Azure Functions version 1.x to version 4.x
When supported, this article takes advantage of ASP.NET Core integration in the isolated worker model, which improves performance and provides a familiar programming model when your app uses HTTP triggers.
Identify function apps to migrate
Use the following Azure PowerShell script to generate a list of function apps in your subscription that currently use the in-process model.
The script uses the subscription that Azure PowerShell is currently configured to use. You can change the subscription by first running Set-AzContext -Subscription '<YOUR SUBSCRIPTION ID>' and replacing <YOUR SUBSCRIPTION ID> with the ID of the subscription you want to evaluate.
$FunctionApps = Get-AzFunctionApp
$AppInfo = @{}
foreach ($App in $FunctionApps)
{
if ($App.Runtime -eq 'dotnet')
{
$AppInfo.Add($App.Name, $App.Runtime)
}
}
$AppInfo
Choose your target .NET version
When migrating to the isolated worker model, choose your target based on whether your function app and its dependencies can run on .NET (formerly .NET Core):
- If your app and its dependencies can run on .NET, target .NET 10.
- If your app depends on libraries or APIs available only in .NET Framework, target .NET Framework 4.8.
Prepare for migration
Before you migrate an app to the isolated worker model, thoroughly review the contents of this guide. Also, familiarize yourself with the features of the isolated worker model and the differences between the two models.
To migrate the application:
- Migrate your local project to the isolated worker model by following the steps in Migrate your local project.
- After migrating your project, fully test the app locally by using version 4.x of the Azure Functions Core Tools.
- Update your function app in Azure to the isolated model.
Migrate your local project
This section outlines the various changes that you need to make to your local project to move it to the isolated worker model. Some of the steps change based on your target version of .NET. Use the tabs to select the instructions that match your desired version.
Tip
If you're moving to .NET 10, the .NET Upgrade Assistant can automatically make many of the changes mentioned in the following sections.
First, convert the project file and update your dependencies. As you do, you see build errors for the project. In subsequent steps, you'll make the corresponding changes to remove these errors.
Project file
The following example shows a .csproj project file that uses .NET 8 on version 4.x:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<RootNamespace>My.Namespace</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
Use one of the following procedures to update this XML file to run in the isolated worker model:
These steps assume a local C# project; if your app instead uses C# script (.csx files), you should convert to the project model before continuing.
The following changes are required in the .csproj XML project file:
Set the
Sdkattribute on theProjectelement toAzure.Functions.Sdk/1.0.0.Set the value of
PropertyGroup.TargetFrameworktonet10.0.In the
ItemGroup.PackageReferencelist, replace the package reference toMicrosoft.NET.Sdk.Functionswith the following references. Keep theMicrosoft.Azure.Functions.Workerpackage as an explicit reference:<FrameworkReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.52.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.1.0" /> <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" /> <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />Make note of any references to other packages in the
Microsoft.Azure.WebJobs.*namespaces. You'll replace these packages in a later step.Add the following new
ItemGroup:<ItemGroup> <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext"/> </ItemGroup>
After you make these changes, your updated project should look like the following example:
<Project Sdk="Azure.Functions.Sdk/1.0.0">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>My.Namespace</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.52.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.1.0" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
<!-- Other packages may also be in this list -->
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext"/>
</ItemGroup>
</Project>
Changing your project's target framework might also require changes to parts of your toolchain, outside of project code. For example, in VS Code, you might need to update the azureFunctions.deploySubpath extension setting through user settings or your project's .vscode/settings.json file. Check for any dependencies on the framework version that might exist outside of your project code, as part of build steps or a CI/CD pipeline.
Package references
When migrating to the isolated worker model, change the packages your application references.
If you haven't already, update your project to use the latest stable versions of:
- Microsoft.Azure.Functions.Worker
- Azure.Functions.Sdk as the project SDK
Depending on the triggers and bindings your app uses, your app might need to reference a different set of packages. The following table shows the replacements for some of the most commonly used extensions:
| Scenario | Changes to package references |
|---|---|
| Timer trigger | Add Microsoft.Azure.Functions.Worker.Extensions.Timer |
| Storage bindings | ReplaceMicrosoft.Azure.WebJobs.Extensions.Storagewith Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs, Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues, and Microsoft.Azure.Functions.Worker.Extensions.Tables |
| Blob bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.Storage.Blobswith the latest version of Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs |
| Queue bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.Storage.Queueswith the latest version of Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues |
| Table bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.Tableswith the latest version of Microsoft.Azure.Functions.Worker.Extensions.Tables |
| Cosmos DB bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.CosmosDBand/or Microsoft.Azure.WebJobs.Extensions.DocumentDBwith the latest version of Microsoft.Azure.Functions.Worker.Extensions.CosmosDB |
| Service Bus bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.ServiceBuswith the latest version of Microsoft.Azure.Functions.Worker.Extensions.ServiceBus |
| Event Hubs bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.EventHubswith the latest version of Microsoft.Azure.Functions.Worker.Extensions.EventHubs |
| Event Grid bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.EventGridwith the latest version of Microsoft.Azure.Functions.Worker.Extensions.EventGrid |
| SignalR Service bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.SignalRServicewith the latest version of Microsoft.Azure.Functions.Worker.Extensions.SignalRService |
| Durable Functions | Replace references toMicrosoft.Azure.WebJobs.Extensions.DurableTaskwith the latest version of Microsoft.Azure.Functions.Worker.Extensions.DurableTask |
| Durable Functions (SQL storage provider) |
Replace references toMicrosoft.DurableTask.SqlServer.AzureFunctionswith the latest version of Microsoft.Azure.Functions.Worker.Extensions.DurableTask.SqlServer |
| Durable Functions (Netherite storage provider) |
Replace references toMicrosoft.Azure.DurableTask.Netherite.AzureFunctionswith the latest version of Microsoft.Azure.Functions.Worker.Extensions.DurableTask.Netherite |
| SendGrid bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.SendGridwith the latest version of Microsoft.Azure.Functions.Worker.Extensions.SendGrid |
| Kafka bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.Kafkawith the latest version of Microsoft.Azure.Functions.Worker.Extensions.Kafka |
| RabbitMQ bindings | Replace references toMicrosoft.Azure.WebJobs.Extensions.RabbitMQwith the latest version of Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ |
| Dependency injection and startup config |
Remove references toMicrosoft.Azure.Functions.Extensions(The isolated worker model provides this functionality by default.) |
See Supported bindings for a complete list of extensions to consider, and consult each extension's documentation for full installation instructions for the isolated process model. Be sure to install the latest stable version of any packages you are targeting.
Tip
Any changes to extension versions during this process might require you to update your host.json file as well. Be sure to read the documentation of each extension that you use.
For example, the Service Bus extension has breaking changes in the structure between versions 4.x and 5.x. For more information, see Azure Service Bus bindings for Azure Functions.
Your isolated worker model application should not reference any packages in the Microsoft.Azure.WebJobs.* namespaces or Microsoft.Azure.Functions.Extensions. If you have any remaining references to these, they should be removed.
Tip
Your app might also depend on Azure SDK types, either as part of your triggers and bindings or as a standalone dependency. You should take this opportunity to update these as well. The latest versions of the Functions extensions work with the latest versions of the Azure SDK for .NET, almost all of the packages for which are the form Azure.*.
Program.cs file
When migrating to run in an isolated worker process, add a Program.cs file to your project with the following contents:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
})
.Build();
host.Run();
This example includes ASP.NET Core integration to improve performance and provide a familiar programming model when your app uses HTTP triggers. If you don't intend to use HTTP triggers, you can replace the call to ConfigureFunctionsWebApplication with a call to ConfigureFunctionsWorkerDefaults. If you do so, you can remove the reference to Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore from your project file. However, for the best performance, even for functions with other trigger types, you should keep the FrameworkReference to ASP.NET Core.
The Program.cs file replaces any file that has the FunctionsStartup attribute, which is typically a Startup.cs file. In places where your FunctionsStartup code would reference IFunctionsHostBuilder.Services, you can instead add statements within the .ConfigureServices() method of the HostBuilder in your Program.cs. To learn more about working with Program.cs, see Start-up and configuration in the isolated worker model guide.
The default Program.cs examples previously described include setup of Application Insights. In your Program.cs, you must also configure any log filtering that should apply to logs coming from code in your project. In the isolated worker model, the host.json file only controls events emitted by the Functions host runtime. If you don't configure filtering rules in Program.cs, you might see differences in the log levels present for various categories in your telemetry.
Although you can register custom configuration sources as part of the HostBuilder, these similarly apply only to code in your project. The platform also needs trigger and binding configuration, and this should be provided through the application settings, Key Vault references, or App Configuration references features.
After you move everything from any existing FunctionsStartup to the Program.cs file, you can delete the FunctionsStartup attribute and the class it was applied to.
Function signature changes
Some key types change between the in-process model and the isolated worker model. Many of these changes relate to the attributes, parameters, and return types that make up the function signature. For each of your functions, make changes to:
- The function attribute, which also sets the function's name
- How the function obtains an
ILogger/ILogger<T> - Trigger and binding attributes and parameters
The rest of this section walks you through each of these steps.
Function attributes
The Function attribute in the isolated worker model replaces the FunctionName attribute. The new attribute has the same signature, and the only difference is in the name. You can therefore perform a string replacement across your project.
Logging
In the in-process model, you could include an optional ILogger parameter for your function, or you could use dependency injection to get an ILogger<T>. If your app already used dependency injection, the same mechanisms work in the isolated worker model.
However, for any Functions that relied on the ILogger method parameter, you need to make a change. Use dependency injection to obtain an ILogger<T>. Use the following steps to migrate the function's logging mechanism:
In your function class, add a
private readonly ILogger<MyFunction> _logger;property, replacingMyFunctionwith the name of your function class.Create a constructor for your function class that takes in the
ILogger<T>as a parameter:public MyFunction(ILogger<MyFunction> logger) { _logger = logger; }Replace both instances of
MyFunctionin the preceding code snippet with the name of your function class.For logging operations in your function code, replace references to the
ILoggerparameter with_logger.Remove the
ILoggerparameter from your function signature.
To learn more, see Logging in the isolated worker model.
Trigger and binding changes
When you changed your package references in a previous step, you introduced errors for your triggers and bindings that you can now fix:
Remove any
using Microsoft.Azure.WebJobs;statements.Add a
using Microsoft.Azure.Functions.Worker;statement.For each binding attribute, change the attribute's name as specified in its reference documentation, which you can find in the Supported bindings index. In general, the attribute names change as follows:
- Triggers typically remain named the same way. For example,
QueueTriggeris the attribute name for both models. - Input bindings typically need
Inputadded to their name. For example, if you used theCosmosDBinput binding attribute in the in-process model, the attribute would now beCosmosDBInput. - Output bindings typically need
Outputadded to their name. For example, if you used theQueueoutput binding attribute in the in-process model, this attribute would now beQueueOutput.
- Triggers typically remain named the same way. For example,
Update the attribute parameters to reflect the isolated worker model version, as specified in the binding's reference documentation.
For example, in the in-process model, a blob output binding is represented by a
[Blob(...)]attribute that includes anAccessproperty. In the isolated worker model, the blob output attribute would be[BlobOutput(...)]. The binding no longer requires theAccessproperty, so you can remove that parameter. So[Blob("sample-images-sm/{fileName}", FileAccess.Write, Connection = "MyStorageConnection")]becomes[BlobOutput("sample-images-sm/{fileName}", Connection = "MyStorageConnection")].Move output bindings out of the function parameter list. If you have just one output binding, you can apply this binding to the return type of the function. If you have multiple outputs, create a new class with properties for each output, and apply the attributes to those properties. To learn more, see Multiple output bindings.
Consult each binding's reference documentation for the types it allows you to bind to. In some cases, you might need to change the type. For output bindings, if the in-process model version used an
IAsyncCollector<T>, you can replace this type by binding to an array of the target type:T[]. You can also consider replacing the output binding with a client object for the service it represents, either as the binding type for an input binding if available, or by injecting a client yourself.If your function includes an
IBinderparameter, remove it. Replace the functionality with a client object for the service it represents, either as the binding type for an input binding if available, or by injecting a client yourself.Update the function code to work with any new types.
Migrate to asynchronous HTTP stream I/O
If an HTTP-triggered function uses ASP.NET Core integration, replace synchronous reads from and writes to HTTP request and response streams with asynchronous methods. Synchronous operations can fail with InvalidOperationException: Synchronous operations are disallowed. For example, replace ReadToEnd with ReadToEndAsync, Write with WriteAsync, WriteString with WriteStringAsync, and Flush with FlushAsync.
When you await these operations, mark the function method as async and wrap its return type in Task<T>. For example, change IActionResult to Task<IActionResult> or MultiResponse to Task<MultiResponse>. ASP.NET Core disallows synchronous request and response I/O by default because synchronous I/O can cause thread pool starvation. If a dependency or serializer doesn't support asynchronous I/O, see JSON serialization with ASP.NET Core integration for instructions to enable synchronous I/O (AllowSynchronousIO) as a compatibility option.
local.settings.json file
The local.settings.json file is only used when running locally. For information, see Local settings file.
When migrating from running in-process to running in an isolated worker process, you need to change the FUNCTIONS_WORKER_RUNTIME value to dotnet-isolated. Ensure that your local.settings.json file has at least the following elements:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
The value you have for AzureWebJobsStorage might be different. You don't need to change its value as part of the migration.
host.json file
No changes are required to your host.json file. However, if your Application Insights configuration is in this file from your in-process model project, you might want to make more changes in your Program.cs file. The host.json file only controls logging from the Functions host runtime. In the isolated worker model, some of these logs come from your application directly, giving you more control. See Managing log levels in the isolated worker model for details on how to filter these logs.
Other code changes
This section highlights other code changes to consider as you work through the migration. These changes aren't needed by all applications, but you should evaluate if any are relevant to your scenarios.
JSON serialization
By default, the isolated worker model uses System.Text.Json for JSON serialization. To customize serializer options or switch to JSON.NET (Newtonsoft.Json), see Customizing JSON serialization.
Because the in-process model used Newtonsoft.Json, also check the serialization attributes on any types your functions bind to. System.Text.Json ignores attributes such as [JsonProperty] and [JsonIgnore] from Newtonsoft.Json. It binds the affected property to its default value without reporting an error. Either replace them with their System.Text.Json equivalents, such as [JsonPropertyName], or configure Newtonsoft.Json for the layer that handles the payload.
Application Insights log levels and filtering
Logs can be sent to Application Insights from both the Functions host runtime and code in your project. The host.json allows you to configure rules for host logging, but to control logs coming from your code, you need to configure filtering rules as part of your Program.cs. See Managing log levels in the isolated worker model for details on how to filter these logs.
HTTP trigger migration example
The following example compares an HTTP-triggered function before and after migration to the isolated worker model.
An HTTP trigger for the in-process model might look like the following example:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
namespace Company.Function
{
public static class HttpTriggerCSharp
{
[FunctionName("HttpTriggerCSharp")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
return new OkObjectResult($"Welcome to Azure Functions, {req.Query["name"]}!");
}
}
}
An HTTP trigger for the migrated version might look like the following example:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
namespace Company.Function
{
public class HttpTriggerCSharp(ILogger<HttpTriggerCSharp> logger)
{
[Function("HttpTriggerCSharp")]
public IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req)
{
logger.LogInformation("C# HTTP trigger function processed a request.");
return new OkObjectResult($"Welcome to Azure Functions, {req.Query["name"]}!");
}
}
}
Update your function app in Azure
After you migrate your local project, update your function app configuration and deploy the migrated code to complete the move to the isolated worker model.
Before you publish your migrated project
Before you publish your updated code project, plan to complete these two changes together:
- Change the
FUNCTIONS_WORKER_RUNTIMEapplication setting todotnet-isolated. - Publish the migrated isolated worker project to your function app.
Each change restarts the app. After you complete the first change, the deployed code and configured runtime don't match, which causes a runtime/payload mismatch error (AZFD0013) until you complete the second change.
When feasible, use a staging slot during the migration. A staging slot gives you these benefits:
- Keeps the temporary error state resulting from the code and runtime mismatch out of production.
- Lets you test the migrated code and configuration before you swap them into production.
You might see errors in the staging slot logs while completing the two changes. Before you swap the slot, confirm that the errors have stopped and that the app works as expected.
Update your function app by using slots
Use the following steps to update your function app to the isolated worker model by using a staging slot:
Create a deployment slot if you haven't already. You might also want to familiarize yourself with the slot swap process and ensure that you can make updates to the existing application with minimal disruption.
Change the configuration of the staging (nonproduction) slot to use the isolated worker model by setting the
FUNCTIONS_WORKER_RUNTIMEapplication setting todotnet-isolated. Don't markFUNCTIONS_WORKER_RUNTIMEas a slot setting.If you're also targeting a different version of .NET as part of your update, change the stack configuration. To do so, see Update the stack configuration. You can use the same instructions for any future .NET version updates you make.
If you have any automated infrastructure provisioning such as a CI/CD pipeline, ensure that the automations are also updated to keep
FUNCTIONS_WORKER_RUNTIMEset todotnet-isolatedand to target the correct .NET version.Publish your migrated project to the staging (nonproduction) slot of your function app.
If you use Visual Studio to publish an isolated worker model project to an existing app or slot that uses the in-process model, it can also complete the previous step for you at the same time. If you didn't complete the previous step, Visual Studio prompts you to update the function app during deployment. Visual Studio presents this update as a single operation, but these updates are still two separate operations. You might still see errors in your logs from the staging (nonproduction) slot during the interim state.
Confirm that your application is working as expected within the staging (nonproduction) slot.
Perform a slot swap operation to apply the changes you made in your staging (nonproduction) slot to the production slot. A slot swap happens as a single update, which avoids introducing the interim error state in your production environment.
Confirm that your application is working as expected within the production slot.
Once you complete these steps, the migration is complete, and your app runs on the isolated model. Congratulations! Repeat the steps from this guide as necessary for any other apps that need migration.