logic apps
405 TopicsLogic Apps Standard custom code now supports .NET 10
The latest Azure Logic Apps (Standard) extension for Visual Studio Code (VS Code) now supports .NET 10 custom code. You can create new .NET 10 local-function projects and migrate your existing .NET 8 projects without turning them into separate Azure Functions apps. Check your prerequisites Install the Azure Logic Apps (Standard) extension for VS Code, version 5.1013.4 . Use Logic Apps Standard extension bundle 1.194.31 . After the extension's dependency setup completes, the .NET 10 software development kit (SDK) and runtime should be installed in its managed dependencies folder. On Windows, the default .NET location is: %USERPROFILE%\.azurelogicapps\dependencies\DotNetSDK Check that installation, rather than relying on the dotnet command elsewhere on your PATH . If you've customized the extension's dependency location, check the configured location instead. New projects target .NET 10 When you create a new custom-code project through the extension, .NET 10 is now the only supported target. The .NET 8 option has been removed for new projects. Existing .NET 8 projects still need a configuration migration before they target .NET 10. Updating the extension isn't the same as retargeting your project. Unchanged project will continue to run on .NET 8 until the configuration changes below are applied. If you use the C# code action If your workflow uses the C# code action, add the runtime setting to your Logic Apps project's settings - either in a local project or on an Azure application. Set LOGIC_APPS_CUSTOMCODE_DOTNETVERSION to net10.0 . Migrate an existing .NET 8 project You don't need to start with a new workspace. Back up your workspace, including local configuration, before making the changes below. Paths are relative to each project's folder. Changes in the custom-code project File or setting Change Project .csproj : target framework Set TargetFramework to net10.0 . Keep the project as a library. Project .csproj : SDK packages Microsoft.Azure.Workflows.Webjobs.Sdk : 1.4.1 Microsoft.Azure.Functions.Worker.Sdk : 2.0.7 Project .csproj : supporting packages Align dependencies as needed. Our migration required: Microsoft.Azure.Functions.Worker : 2.51.0 Existing Microsoft.Extensions.Logging : 10.0.0 Existing Microsoft.Extensions.Logging.Abstractions : 10.0.0 Project .csproj : dependency copying and publication Set CopyLocalLockFileAssemblies to true . Keep build-triggered publication into the Logic Apps folder. .vscode\settings.json Update the framework segment of azureFunctions.deploySubpath to net10.0 . Those package versions describe the configuration we tested, not a universal minimum dependency set. Resolve the dependencies your project actually needs rather than copying every package from a sample. A sample project file will look like this <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <IsPackable>false</IsPackable> <TargetFramework>net10.0</TargetFramework> <AzureFunctionsVersion>v4</AzureFunctionsVersion> <OutputType>Library</OutputType> <PlatformTarget>AnyCPU</PlatformTarget> <LogicAppFolderToPublish>$(MSBuildProjectDirectory)\..\{your logic app target folder}</LogicAppFolderToPublish> <CopyToOutputDirectory>Always</CopyToOutputDirectory> <SelfContained>false</SelfContained> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Abstractions" Version="1.3.0"/> <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.51.0"/> <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.7"/> <PackageReference Include="Microsoft.Azure.Workflows.Webjobs.Sdk" Version="1.4.1"/> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0"/> <PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.0"/> </ItemGroup> <Target Name="TriggerPublishOnBuild" AfterTargets="Build"> <CallTarget Targets="Publish"/> </Target> </Project> Changes in the Logic Apps project File or setting Change local.settings.json : custom-code runtime Set Values.LOGIC_APPS_CUSTOMCODE_DOTNETVERSION to net10.0 . local.settings.json : host runtime flag Keep Values.FUNCTIONS_INPROC_NET8_ENABLED set to 1 . This is still required. .vscode\launch.json : coordinated debugging Use a launch configuration with: type=logicapp and request=launch funcRuntime=coreclr customCodeRuntime=coreclr isCodeless=true Verify the migration Save all files, restore, and build. Confirm publication under lib\custom\net10.0 in the Logic Apps folder, then run the workflow that calls your edited function and verify its breakpoint. Use the ready-made migration skill We've prepared the logicapps-custom-code-net10-migration skill to guide a coding agent through the same process. It inspects your workspace, plans configuration changes before applying them, and guides build and publication verification. It preserves your function and workflow implementations rather than rewriting them. The skill is available in Awesome Copilot. With GitHub CLI (command-line interface) version 2.90.0 or later, inspect the skill and install it for Copilot across projects. These skill commands are currently in preview. gh skill preview github/awesome-copilot logicapps-custom-code-net10-migration gh skill install github/awesome-copilot logicapps-custom-code-net10-migration --agent github-copilot --scope user Installation makes the skill available to Copilot; it doesn't run the migration. After installation, you can ask your agent: Migrate this Logic Apps Standard .NET 8 custom-code workspace to .NET 10 using the logicapps-custom-code-net10-migration skill. Preserve my workflows, back up the project first, and include coordinated VS Code debugging. Keep the host and deployment settings in view The custom-code target framework isn't the Logic Apps host runtime. Keep the existing host settings, including FUNCTIONS_WORKER_RUNTIME=dotnet . Don't switch the host to dotnet-isolated just because the custom code targets .NET 10. Preserving your existing code is the migration's starting point, not a guarantee that it will build and run unchanged. Use the build and an executed local function to check the result. For Azure execution, the deployed Logic Apps application settings must include both LOGIC_APPS_CUSTOMCODE_DOTNETVERSION=net10.0 and FUNCTIONS_INPROC_NET8_ENABLED=1 . The .NET 8 host flag is still required even though your custom code targets .NET 10. When you deploy through the Logic Apps extension in VS Code, these settings are copied to the Azure app. If you deploy through a pipeline, make sure your deployment configuration explicitly includes both application settings. A local settings file alone doesn't configure the Azure app, so verify the deployed runtime configuration after deployment. The migration skill doesn't change Azure resources as a side effect. Try the updated extension with one of your custom-code projects. If migration or debugging needs a step we've missed, share the configuration and the symptom in the comments, without credentials or private data. I want to hear where the build or debugging experience still gets in your way.881Views0likes15CommentsMigrate NuGet-based Logic Apps Standard apps and custom built-in connectors to .NET 10
Less than you might fear. You don't change a line of C#, and you don't touch your workflow definitions. The work is retargeting your projects, resolving a couple of dependency conflicts, running the right host locally, and changing a handful of app settings in Azure. Those last two are where people get stuck, so I spend most of this post on them. This is a companion to Logic Apps Standard custom code now supports .NET 10. That post covers custom-code (local function) projects. This one covers NuGet-based applications and the custom built-in connectors they consume, and it answers the questions you left in the comments on the custom code post. We validated every step below end to end, locally and in Azure, with a NuGet-based sample app and a custom built-in connector. Which post do you need? Your Logic Apps Standard app What to do Workflows only, bundle-based No project changes. The platform moves the app to the out-of-proc host. Workflows plus a custom-code (local function) project Follow the custom code .NET 10 post. NuGet-based project, with or without custom built-in connectors Follow this post. NuGet-based project that also has a custom-code project Use this post for the app and connectors, and the custom code post for the function project. Your code stays the same Your code don't change. Keep the [assembly: WebJobsStartup] attribute, your IWebJobsStartup.Configure method and your IServiceOperationsProvider implementation exactly as they are. Your workflow definitions don't change either. You don't add an isolated worker project or a Program.cs file. We validated this with a sample custom built-in connector that exposes an action, locally and in Azure. That tells you the model works. It doesn't tell you your connector works. Your connectors and their dependencies still need application-specific testing, and I come back to that in the limitations section. First, understand which host runs your app A connector built for net10.0 needs a .NET 10 host. The .NET 8 host can't load it: every type fails with a missing System.Runtime 10.0.0.0 reference. So the whole migration comes down to two things: building for net10.0 , and making sure a .NET 10 host runs the result. Azure and your local tools choose that host in different ways, and this is the part that catches people out: Where FUNCTIONS_WORKER_RUNTIME What selects the .NET 10 host Azure dotnet (unchanged) Removing LOGICAPP_INPROC_REDIRECT . Without it, the platform runs your app on the out-of-proc host on .NET 10. Local (Azure Functions Core Tools) dotnet-isolated Core Tools ignores LOGICAPP_INPROC_REDIRECT . With dotnet it always picks its .NET 8 in-process host. With dotnet-isolated , Core Tools 4.16.0 or later uses its main host, which runs on .NET 10. dotnet-isolated doesn't move you to the isolated worker model. The Workflows runtime and your connector still load into the host process; the value only changes which host Core Tools starts. That's also why it's a local-only value. Keep it out of your Azure app settings and deployment templates. This is a current limitation of the the extension and we are working to remove this extra configuration step. Check your prerequisites The .NET 10 SDK, version 10.0.403 or later. The Azure Logic Apps (Standard) extension for VS Code, version 5.1013.4, installs it in the extension's managed dependencies folder. On Windows the default is %USERPROFILE%\.azurelogicapps\dependencies\DotNetSDK . Azure Functions Core Tools 4.16.0 or later, the first version whose main host runs on .NET 10. The extension installs a managed copy in %USERPROFILE%\.azurelogicapps\dependencies\FuncCoreTools . An older copy installed through npm and earlier on your PATH (4.12.0 in our testing) runs on .NET 8 and fails to start the app. Microsoft.Azure.Workflows.WebJobs.Extension 1.170.91 or later. The current version at the time of this post on NuGet is 1.194.31, which is the version we validated. Use the latest version you have available as it will have the latest product improvements and fixes. Microsoft.NET.Sdk.Functions 4.5.0 or later. We validated 4.5.0 and 4.6.0. Write access to the package feed where you publish your connector packages. A build agent image with the .NET 10 SDK for your pipeline. Keep your current deployment stable while you migrate If your app runs on .NET 8 today, leave its app settings alone until your .NET 10 build is validated and ready to deploy. Retaining the existing app settings preserves the current compatibility configuration while you prepare and validate the migration. For NuGet-based apps, that includes LOGICAPP_INPROC_REDIRECT=1 , the setting that keeps your app on the legacy .NET 8 in-proc host. Remove it early and the app moves to the new host on its next restart, before your .NET 10 build is in place. Check your pipelines too. A release that rebuilds app settings from a template can drop the redirect without anyone noticing. Don't treat this as a reason to wait. .NET 8 apps keep running after end of support, but they no longer receive security fixes. Plan the migration now. Update your project files Work on a branch, and back up any local configuration before you start. This table lists every file that changed in our validated migration. Repeat the connector changes for every connector project your app consumes. File Change global.json (repository root and Logic Apps project folder) Set the SDK version to 10.0.403 or later, with rollForward set to latestPatch . A leftover 8.0 pin fails the build with NETSDK1045 . Connector .csproj Set TargetFramework to net10.0 . Reference Microsoft.Azure.Workflows.WebJobs.Extension 1.194.31. Add direct references for any NU1605 downgrades restore reports. Increment the package version (2.0.0 in our sample) so you can tell which connector loaded. Connector startup and provider classes No change. Connector test projects Set TargetFramework to net10.0 . Logic Apps .csproj Set TargetFramework to net10.0 . Reference Microsoft.NET.Sdk.Functions 4.5.0 or later, Microsoft.Azure.Workflows.WebJobs.Extension 1.194.31 and your new connector package version. Keep the targets that copy the lib folder and your artifacts into the publish output. host.json Remove any extensionBundle section. Keep version 2.0 and your existing logging and settings. local.settings.json Set FUNCTIONS_WORKER_RUNTIME to dotnet-isolated . .vscode/settings.json Point deploySubpath at bin\Release\net10.0\publish . .vscode/tasks.json Set the cwd of the func host start task to bin\Debug\net10.0 , in every operating system block. Build and deployment scripts Replace net8.0 output paths with net10.0 . Pin the SDK Update global.json in the repository root and in the Logic Apps project folder: { "sdk": { "version": "10.0.403", "rollForward": "latestPatch" } } Retarget the connector and resolve downgrades Restore is where the first failure shows up. In our sample, retargeting the connector with Workflows 1.194.31 produced NU1605 package downgrade errors, and two direct references fixed them: net10.0 true Contoso.LogicApps.Connectors.Inventory 2.0.0 Those were the right pins for our connector's dependency graph. Yours may need different ones, so read the NU1605 output and pin what it names rather than copying ours. If restore also reports vulnerability warnings, review them; don't suppress them as part of the migration. Then build, pack, and publish the new version to your feed: dotnet build -c Release dotnet pack -c Release -o ./nupkg dotnet nuget push ./nupkg/Contoso.LogicApps.Connectors.Inventory.2.0.0.nupkg --source If your Logic Apps project references the connector as a project reference rather than a package, skip the pack and push. The retarget and the dependency fixes still apply. Retarget the Logic Apps project The relevant parts of the project file: <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net10.0</TargetFramework> <AzureFunctionsVersion>v4</AzureFunctionsVersion> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.5.0" /> <PackageReference Include="Microsoft.Azure.Workflows.WebJobs.Extension" Version="1.194.31" /> <PackageReference Include="Contoso.LogicApps.Connectors.Inventory" Version="2.0.0" /> </ItemGroup> <!-- Keep your existing None/Update items and CopyDynamicLibraries target. --> </Project> Don't remove Microsoft.NET.Sdk.Functions . It generates bin\extensions.json , which registers your connector with the host. Without it, the connector is missing from the build output. A NuGet-based app loads the Workflows runtime from your package, not from an extension bundle, so host.json needs no bundle: { "version": "2.0" } Version 5.1013.4 of the extension have a configuration bug. It is ignoring the following extension configuration set: "azureLogicAppsStandard.enableProjectConsistencyChecks": false With that your host.json file will include the extension bundle setting again when the project opens: "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle.Workflows", "version": "[1.*, 2.0.0)" } Remove it before pushing to source control or running the application. We are working on a fix for this issue which will ship with the next version of the bundle. Why a net8.0 package works in a net10.0 project Microsoft.Azure.Workflows.WebJobs.Extension targets net8.0 . That doesn't stop a net10.0 project from referencing it: NuGet treats net10.0 as compatible and selects the package's net8.0 assets. What has to be .NET 10 is the host that runs your app. There's one side effect worth knowing about. On net10.0 , the SDK resolves the package's ASP.NET Core framework reference to version 10, which already contains Microsoft.Extensions.DependencyInjection and related assemblies, so the build leaves the package copies out of your output. That's expected. The .NET 10 host supplies them, which is one more reason the app only runs on that host. Run and verify locally Set the worker runtime in local.settings.json and keep your other values as they are: { "IsEncrypted": false, "Values": { "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated" } } Make sure Core Tools 4.16.0 or later is the func that runs. If you start the host from a terminal or a script, check that the managed copy, not an older npm install, comes first on your PATH . The version banner tells you which one started. Stop the host serving this project if it's running, then restore and build the Logic Apps project. Start the host from bin\Debug\net10.0 . Check the host log. There should be no '/serviceProviders/' ... is not valid error, and your workflows should be listed. Run a workflow for every operation you ship, triggers included, and check the run history. Optionally, open a workflow in the designer, select Built-in, and confirm your connector's operations appear. You may see Could not find the .azurefunctions folder in the deployed artifacts of a .NET isolated function app in the log. It's a warning that comes with the dotnet-isolated selection, and the workflows still run. Update the Azure app settings In Azure, the platform selects the .NET 10 host when LOGICAPP_INPROC_REDIRECT is absent, and FUNCTIONS_WORKER_RUNTIME stays dotnet . These are the settings we changed and the ones we left alone: Setting Action AzureFunctionsJobHost__extensionBundle__id Delete. AzureFunctionsJobHost__extensionBundle__version Delete. App settings override host.json , so removing the bundle from the file alone isn't enough. LOGICAPP_INPROC_REDIRECT Delete if present. It forces the legacy .NET 8 host. FUNCTIONS_WORKER_RUNTIME Keep dotnet . dotnet-isolated is the local-only value. FUNCTIONS_EXTENSION_VERSION Keep ~4 . APP_KIND Keep workflowApp . FUNCTIONS_INPROC_NET8_ENABLED Not required. It's harmless if it's left over from .NET 8. netFrameworkVersion (site configuration) No change. It stays v8.0 and doesn't decide which runtime loads. The extension bundle settings are the easiest to miss. Apps created in the Azure portal usually get them by default. If either is present, the host loads the Workflows runtime from the bundle instead of your package, your connector never registers, and the log reports that '/serviceProviders/' is not valid. Your deployed package can be perfectly correct and still fail this way. Keep your deployment template at dotnet as well, and make sure it doesn't add the bundle settings or the redirect back on the next release. Deploy and verify in Azure Update your pipeline to build with the .NET 10 SDK, publish a Release build, and deploy the contents of bin\Release\net10.0\publish . Deploy to a non-production app or deployment slot first. For an existing app, stop it, change the app settings, deploy the .NET 10 package, and then start it. In that order, the new package never starts under the old configuration. Check the host log for the '/serviceProviders/' ... is not valid error. It shouldn't be there. Confirm that each workflow that uses your connector shows its callback URL, and that a test run succeeds. Optionally, open Process Explorer in Kudu and confirm the loaded modules: CoreCLR 10, your connector DLL at its new version, and the Workflows runtime at 1.194.31. That's the reliable way to see which runtime is running, because the settings don't tell you. Compare run history with the .NET 8 version, then promote the same build and the same settings to production. A local settings file doesn't configure the Azure app. After each deployment, check the app settings on the deployed resource rather than trusting the template. If you need to roll back, redeploy the .NET 8 package and restore LOGICAPP_INPROC_REDIRECT=1 . Restoring the setting on its own isn't enough, because the .NET 8 host can't run a .NET 10 connector. Symptoms and causes If something fails, start here. These are the errors we hit during validation: Symptom Cause and fix NETSDK1045: The current .NET SDK does not support targeting .NET 10.0 A global.json pin or the selected SDK is still 8.0. Pin 10.0.403 or later. NU1605 package downgrade errors on restore Transitive dependency versions in your connector. Add direct references for the packages restore names. Locally: Could not load file or assembly 'Microsoft.Extensions.DependencyInjection, Version=9.0.0.0' FUNCTIONS_WORKER_RUNTIME is dotnet , so Core Tools started its .NET 8 in-process host. Set dotnet-isolated in local.settings.json . Locally: Could not load file or assembly 'System.Text.Json, Version=9.0.0.0' An older Core Tools whose host runs on .NET 8 is first on your PATH . Use 4.16.0 or later. '/serviceProviders/' ... is not valid , and no callback URL An extension bundle is configured in host.json or in the AzureFunctionsJobHost__extensionBundle__* app settings. Remove both. Connector and bin\extensions.json missing from the build output Microsoft.NET.Sdk.Functions was removed from the Logic Apps project. Add it back. Use the migration skill We've prepared the logicapps-nuget-connector-net10-migration skill to guide a coding agent through the same process. It inspects your solution, plans configuration changes before applying them, and guides build and test verification. It preserves your connector code and workflows rather than rewriting them, and it doesn't change Azure resources: it lists the app-setting changes for you to make. The skill is available in the custom-connector-migration-net10 repository, with a working sample. The main branch holds the migrated .NET 10 version and the net8.0 branch holds the .NET 8 baseline, so you can try the skill on the sample before your own projects. With GitHub CLI (command-line interface) version 2.90.0 or later, inspect the skill and install it for Copilot across projects. These skill commands are currently in preview. gh skill preview wsilveiranz/custom-connector-migration-net10 logicapps-nuget-connector-net10-migration gh skill install wsilveiranz/custom-connector-migration-net10 logicapps-nuget-connector-net10-migration --agent github-copilot --scope user Installation makes the skill available to Copilot; it doesn't run the migration. After installation, you can ask your agent: Migrate this NuGet-based Logic Apps Standard app and its custom built-in connector to .NET 10 using the logicapps-nuget-connector-net10-migration skill. Preserve my connector code and workflows, back up the projects first, and list the Azure app settings I need to change. Note: we're submitting this skill to Awesome Copilot. When it's available there, we'll update this post with the new install commands. Your questions, answered Do I need to change how my custom built-in connector registers? No. The existing registration model remains applicable: retain your IWebJobsStartup registration and IServiceOperationsProvider implementation. We validated a custom built-in connector with this model on the .NET 10 host, locally and in Azure. Your connectors and their dependencies still need application-specific testing. Microsoft.Azure.Workflows.WebJobs.Extension targets net8.0. Can a net10.0 app reference it? Yes. The package's net8.0 target doesn't prevent a net10.0 application from referencing it. A target framework isn't a requirement that the consuming application use exactly that framework. What does have to be .NET 10 is the host that runs your app. You still need to validate dependency compatibility, and restore tells you where to look. I'm already on 1.194.31. Do I need to downgrade to 1.170.91? No. 1.194.31 is newer than the 1.170.91 minimum in our migration guidance, and it's the version we validated. Stay where you are. Do I need to move to the isolated worker model? No. You don't add a worker project or a Program.cs file, and your connector still loads into the host process. dotnet-isolated is only the value that makes Core Tools start its .NET 10 host on your machine. In Azure, FUNCTIONS_WORKER_RUNTIME stays dotnet . What should I do with my existing .NET 8 deployment in the meantime? Keep its existing app settings. They preserve the current compatibility configuration while you prepare and validate the migration. Remove LOGICAPP_INPROC_REDIRECT when you deploy the .NET 10 package, not before. When will the official documentation cover NuGet-based apps and custom built-in connectors? We know you need explicit guidance for this scenario, and this post is that guidance today. We don't have a confirmed publication date for the Microsoft Learn update. Don't wait for it: migrate to .NET 10 at your earliest opportunity. Before you migrate: what we haven't covered We validated a sample connector with an action, not yours, and not a connector with triggers. Connectors that implement IServiceOperationsTriggerProvider , connectors with their own converters, and connectors with third-party libraries that pin older framework versions are where I'd expect surprises. Test every operation. We haven't validated an app that combines a NuGet-based project with a custom-code project. In our sample, the generateDebugSymbols prelaunch task in VS Code failed, because it looks up an extension bundle path and a NuGet-based project doesn't have one. Don't add a bundle to work around it; start the host from bin\Debug\net10.0 instead. We are working on a fix for this problem. The Microsoft Learn article Create custom built-in connectors for Standard workflows still describes a .NET Core 3.1 class library project. Until it's updated, use this post as the reference for the target framework. Don't pin your app to a specific extension bundle or Functions host version. Pinned apps needed manual updates during the out-of-proc migration, and they will again every time the platform moves. Call to action Retarget one connector this week and run it against a non-production app. If something fails, check the symptoms table first. If your error isn't there, post the connector shape (actions, triggers, converters), the package versions, and the error in the comments, without credentials or private data. I'll take the patterns back to the team and fold them into this post and the skill.Logic Apps Aviators Newsletter - November 2026
In this issue: Ace Aviator of the Month News from our product group News from our community Ace Aviator of the Month November 2026's Ace Aviator: Steef-Jan Wiggers Coöperatie VGZ What's your role and title? What are your responsibilities? I'm a Domain Architect Technology in the Business Change department at VGZ, one of the largest health insurers in the Netherlands. I'm responsible for defining architecture building blocks and target architectures. I also investigate which technologies can help us and what changes our IT landscape needs to support the IT capabilities VGZ requires. Can you give us some insights into your day-to-day activities and what a typical day in your role looks like? Each week starts on Monday with our week start, where I meet with peers on a range of architectural topics. From there, no two weeks are the same. I create target architectures for IT capabilities such as integration, cloud, artificial intelligence and, most recently, search. These building blocks describe the “what” and feed into solution architecture, which works out the “how”. Getting to a well-defined target architecture means talking every day with peers and stakeholders across the organisation. I also make time to explore new technology hands-on, to see whether it fits our needs. I share what I find internally in what we call Business Change colleges, knowledge sessions for colleagues. And I'm in frequent contact with Microsoft, both the local team in the Netherlands and the product groups in Redmond. What motivates and inspires you to be an active member of the Aviators/Microsoft community? I've worked in integration for over 20 years. I started with BizTalk Server and today I work with Azure Integration Services. Along the way I've designed, built and deployed many integration solutions, on-premises, hybrid and in the cloud. I've always enjoyed sharing what I learn with peers, through blogging, writing books, editing for InfoQ, and speaking at user groups and conferences such as Integrate and NIS. Sharing knowledge comes back to you many times over: it has given me great opportunities, and above all many friends in the community. Looking back, what advice do you wish you had been given earlier that you'd now share with those looking to get into STEM/technology? Stay curious, and don't wait until you feel like an expert to share what you know. Writing a blog post, giving a talk at a local user group, or just asking questions in the community speeds up your learning enormously and connects you with people who will help you grow. Also, learn the fundamentals well. Technologies change; integration went from BizTalk to Logic Apps. But patterns, principles and how you approach a problem last a whole career. What has helped you grow professionally? Curiosity about how things work. I learn by trying things out and building demos, and I read a lot: books, blogs, documentation. Attending, and later speaking at, user groups and conferences has been just as important. So has staying close to Microsoft, locally and with the product groups in Redmond. The conversations with peers and product teams have taught me as much as any technology. If you had a magic wand that could create a feature in Logic Apps, what would it be and why? A seamless, browser-based development experience with native GitHub integration. The designer in the browser offers the best experience for building Logic Apps, better than VS Code. But today, getting a workflow into source control means exporting it, working locally, and then pushing it. I'd love to do it all in the browser: design the Logic App, commit it straight to the repository, and let a pipeline deploy it to the other environments. That would bring the ease of the designer and proper DevOps practices together. News from our product group Introducing the Logic Apps local CLI: develop Standard workflows from your terminal Microsoft has introduced a public preview Azure CLI extension for local Logic Apps Standard development. It supports project creation, connector discovery, connection configuration, runtime management, workflow validation, and execution diagnostics from the terminal. Developers can invoke commands directly, automate them in scripts, or let coding agents use them with approval. The extension complements the visual designer and existing Azure resource-management commands rather than replacing them. An accompanying Copilot skill guides schema discovery, authentication choices, validation, and execution checks, helping teams ground development and review in observable tool results instead of assumptions. Hybrid Logic Apps - SQL as storage provider benchmarking This benchmark examines SQL Server storage behavior under a file-triggered Hybrid Logic Apps workload in a disconnected, single-node OpenShift environment. SQL Server 2025, file storage, and the cluster share one Windows host and backing disk. Two thirty-minute tests recorded no failed runs; the one-hour dashboard showed 45,821 successful executions. SQL averaged 1.83% of host CPU capacity, while storage contention and tail latency remained important scaling considerations. The article recommends dedicated storage as volumes grow and capacity planning based on peak and tail measurements, stressing that these results describe one workload rather than a general capacity guarantee. 🆕Orchestrate Foundry Prompt and Hosted Agents with Logic Apps Automation Logic Apps Automation can orchestrate Microsoft Foundry Prompt Agents and Hosted Agents as steps in business workflows. API calls, schedules, and connector events can trigger agents, with deterministic actions gathering inputs and validating or acting on outputs. The article distinguishes configured Prompt Agents from container-based Hosted Agents that support custom code and orchestration. Logic Apps provides branching, retries, timeouts, parallel execution, and run history around agent calls. It also outlines a migration path ahead of Foundry workflows retiring on December 1, 2026, helping teams move interactive agents into traceable, event-driven business processes. From Form to Action: A Governed, Event-Driven AI Intake Pipeline with Azure Integration Services This reference architecture turns document-heavy permit intake into governed, asynchronous processing with Azure Integration Services and Microsoft Foundry. API Management controls entry and model access, while Logic Apps validates, enriches, and routes submissions to Service Bus. An Azure Function uses Document Intelligence and a Foundry model before writing a case record and publishing an Event Grid event. A shared correlation ID connects intake, processing, and downstream notifications. The article emphasizes durable hand-off, explicit failure handling, controlled model consumption, and traceability, with an accompanying repository that supports offline exploration without an Azure subscription. 💲Announcing Free Grant and Pricing for Logic Apps Automation Microsoft has announced pricing and free grants for Logic Apps Automation, currently in public preview. Monthly allowances per Azure subscription include 108,000 workflow execution-seconds, 1 GB of data retention, 1,000 Standard and 500 Enterprise managed connector calls, knowledge storage, and AI usage. One managed environment is free only for the first sixty days, unlike the recurring monthly usage grants. Usage beyond the included limits is billed separately. The article explains how teams can experiment and run initial automations within those allowances, then plan paid usage as business process and AI orchestration workloads grow. News from our community Logic Apps Community Day 2026: Agenda and Speakers Announced Event by Ahmed Bayoumy and Sebastian Meyer The agenda and speaker lineup for Logic Apps Community Day 2026 are now published, with the event taking place on December 3, 2026. This free, online community event will stream live on YouTube and is open to attendees worldwide. Eight talks combine longer sessions and lightning talks, covering AI and automation, enterprise architecture, production operations, scalability, and BizTalk migration. Q&A slots between talks provide opportunities to engage with the speakers. The official event page includes the full agenda, speaker details, and an option to add the event to a calendar. Don't Rebuild Your Workflows Inside Agents: Calling Azure Logic Apps from Microsoft Foundry, Securely Post by Rob McKenna Enterprise agents can reuse reviewed business processes rather than duplicate workflow logic inside prompts or agent code. This article demonstrates a Microsoft Foundry agent invoking a Logic Apps workflow through an OpenAPI tool, using managed identity and Entra authorization instead of SAS keys. A synthetic prior-authorization scenario combines a lookup, business-day calculation, escalation, and notification before returning a plain-language response. The approach keeps business rules in the existing workflow while separating conversational interaction from execution, providing a concrete pattern for securely exposing established integrations as agent tools. When Liquid transform in Logic Apps doesn't Behave like Liquid: A subtle string to integer pitfall Post by Şahin Özdemir Generating a date ten years ahead exposes a subtle type-conversion problem in Logic Apps Liquid transformations. The underlying DotLiquid implementation can treat a formatted year as a string, producing concatenation rather than the expected arithmetic result. Common integer-conversion techniques do not reliably resolve the issue. The article demonstrates converting through a floating-point value with the Times: 1.0 filter and applying Round before completing the calculation. This practical example helps integration developers distinguish Liquid syntax from runtime-specific behavior and avoid prolonged debugging of seemingly simple transformation logic. Logic Apps Standard brings freedom Post by Mikael Sand Choosing between Logic Apps Consumption and Standard involves more than comparing per-action charges with a fixed runtime cost. This article argues that Standard allows integration design to focus on business requirements rather than minimizing transactions, particularly when built-in operations process large volumes of records. It describes greater cost predictability within runtime capacity while acknowledging additional infrastructure ownership and networking complexity. Capacity, connectivity, DNS, routing, and firewall configuration remain operational responsibilities. The comparison helps teams weigh architectural flexibility against management overhead when treating integration as a strategic platform capability. Logic Apps and AI Agents: Building Agentic Workflows on Azure Integration Services Post by Mirko Peters Agentic integration design requires choosing an appropriate platform owner as well as connecting a model to business systems. This guide compares Logic Apps with Power Automate, distinguishing Azure resource management, managed identities, infrastructure templates, and monitoring from maker-oriented environments and governance. It explains agent workflow concepts and describes tools as named collections of actions with clear responsibilities. Model configuration and pricing vary by hosting plan, and some capabilities remain in preview. The discussion helps architects separate ownership, tool design, and runtime considerations before building AI-driven business processes. Microsoft Fabric and Logic Apps Side by Side Video by Sebastian Meyer Connecting real-time analytics to operational workflows allows detected business events to initiate action rather than remain dashboard observations. This video demonstrates combining Microsoft Fabric Real-Time Intelligence with business processes built in Logic Apps. The accompanying post describes events arriving from coffee stores and handing relevant information to the integration platform through the Logic Apps Automation SKU. The example separates event detection on the data platform from process execution on the integration platform, illustrating how teams can connect these responsibilities without treating analytics and business automation as unrelated systems. Getting Started Logic App Standard in Azure Video by Stephen W. Thomas Moving locally developed workflows into Azure requires a configured hosting environment as well as a deployment step. This fourteen-minute walkthrough demonstrates creating a Logic Apps Standard environment and deploying a local project from Visual Studio Code. It covers the Workflow Service Plan, storage, application settings, portal-based workflow creation, and connection-string management. The accompanying post also highlights removing the unused hosting plan during demo cleanup to stop further charges. The tutorial gives developers a practical sequence for taking local integration work into the cloud while considering configuration and resource lifecycle. Azure Logic Apps Automation: A New Approach to Dynamic, AI-Powered Business Process Automation Post by Manoj Sethuraman Business processes involving unstructured information, changing rules, and frequent exceptions can be difficult to express as fully predefined workflows. This article introduces Logic Apps Automation as an adaptive approach combining contextual AI decisions, organizational knowledge, human involvement, and enterprise integrations. It outlines project boundaries for governance and isolation, deployable applications containing process assets, and executable workflows combining triggers and actions. The comparison with traditional deterministic automation helps architects consider where runtime flexibility is useful while retaining explicit boundaries around deployment, oversight, and integration responsibilities across business functions. 📈 Daily Exchange Rates, Zero Manual Effort: D365FO + Logic Apps Post by Anitha Eswaran Daily exchange-rate imports can become repetitive and error-prone when an SFTP folder retains both historical and newly delivered files. This article describes a Logic Apps integration that identifies current-day files before submitting them to Dynamics 365 Finance and Operations through an enqueue-based approach. A scheduled workflow starts after the expected delivery time, lists files with the built-in SFTP connector, and evaluates metadata to filter processing. The example demonstrates how selection and validation steps reduce repeated historical imports and unnecessary work while automating a recurring finance integration requirement. What's New with Logic Apps Automation Post by Sagar Sharma The NIS 2026 updates connect Logic Apps Automation capabilities with practical environment and subscription planning. This recap covers managed AI models, reusable templates, development-platform connectors, and orchestration of Foundry and managed agents. It separates agent construction and governance from workflow triggering and business-system integration. Pricing combines a managed-environment base fee, compute that scales to zero, and optional capabilities, alongside free allowances. The article also distinguishes announced features from roadmap items, helping integration architects assess operational ownership, environment counts, and experimentation costs before designing an automation platform. Coders, What's new with Low Code Logic Apps? Post by Sagar Sharma Integration developers need local build, test, debug, and deployment loops that work with source control and coding agents. This NIS recap examines the Logic Apps Standard SDK, which expresses workflows through typed C# and a fluent API, allowing compiler feedback to catch mistakes earlier. It also discusses the local CLI lifecycle and Connector Namespace as managed connectivity for applications and agents. The article frames these capabilities as complementary developer surfaces, helping teams combine low-code orchestration with familiar software-engineering practices while checking release details before relying on illustrative commands. BizTalk End of Support: Logic Apps Migration Agent, Hybrid and Microsoft Migration Incentives Post by Sagar Sharma Planning a BizTalk migration requires more than waiting for the support deadline or converting individual artifacts. This article reviews lifecycle considerations and introduces the AI-assisted Logic Apps Migration Agent for assessing, planning, converting, validating, and deploying workloads to Standard. Three Copilot agents share a five-stage pipeline, with human approval between stages. The discussion also covers map reuse, hybrid deployment, and migration incentives. It positions tooling as an accelerator rather than a replacement for architectural judgment, helping teams structure discovery and validation around the dependencies and business behavior of an existing integration estate.305Views0likes0CommentsHybrid Logic Apps - SQL as storage provider benchmarking
Key findings for technical decision makers Hybrid Logic Apps ran a high-volume, file-driven integration workload on deliberately modest on-premises hardware: one host shared by the cluster, file storage and SQL Server 2025. Across both 30-minute tests there were no failed runs, and the one-hour dashboard view showed 45,821 successful runs at a 100% success rate. The database was not a cost driver: SQL Server used an average of 1.83% of host CPU capacity. Most runs finished in about 4 seconds, with a longer tail for the slowest 1%. The factor that most affects scale is storage, not server count, because adding workflow instances does not add disk capacity. For planning, budget for dedicated storage for the database and files as volumes grow, size capacity on peak and tail response times rather than averages, and validate with your own workloads. These results are a baseline for one workload, not a product-wide capacity guarantee. A practical look at throughput, latency, reads, writes, and locks The primary goal of this exercise is to evaluate SQL read and write behavior and the time spent waiting for locks under integration load. Workflow throughput supplies the workload context; it is not a substitute for those database measurements. This is a mixed-workload observation, not an isolated SQL capacity test. In a 30-minute baseline, files were offered to an Azure Logic Apps workflow at approximately 100 files per second. SQL CPU usage remained low, while a substantial file backlog accumulated. The lesson is not that one component is necessarily slow. It is that a useful benchmark must connect offered load, completed throughput, latency, and waiting rather than treating any one metric as the answer. The SQL comparison tells a different story from workflow throughput alone: average workflow-state data-file write I/O latency rose from 12.958 to 38.652 ms, while accumulated instance-wide lock waiting remained near 1,470 task-seconds. Faster workflow completion did not mean that every SQL measurement improved. A repeat of the same 30-minute workload subsequently showed 3.87% higher successful throughput, 6.40% lower p95 execution latency, and 8.68% lower p99 execution latency, with no failed workflow runs in either measured window. Both measurements are retained below: the repeat was an observed improvement, not proof of a tuning change or a product-wide performance guarantee. The workflow The workflow snapshot shows the processing sequence used in the benchmark. The workflow is taken such that huge set of I/O operations are performed during the workflow executions to simulate the SQL benchmarking under high I/O operations. The workflow performs six steps: Detect a newly created file in a receiving folder. Insert a business record into SQL. Read the source file's contents. Create a copy in a destination folder. Delete the source file. Delete the destination copy. This is a synthetic processing-and-cleanup scenario, not an archival workflow: both test-file copies are removed on successful completion. A successful run means that the complete sequence finished, not just that the SQL insert succeeded. Infrastructure: OpenShift K8se cluster with single node, one shared disk The deployment topology is a hosted Windows machine running an on-premises, single-node OpenShift cluster in a Linux VM, with local SMB storage and SQL Server 2025 on the same Windows host. The SMB files, SQL data and transaction logs, and cluster VM storage all share the same host drive and backing disk. Different folders or virtual disks on that shared backing disk do not create independent I/O capacity. The workflow operates in a fully disconnected runtime environment: the execution and data paths shown remain local, without an external runtime-service dependency for this workflow. This documents the supplied runtime topology, not an independent network-isolation test or a claim about offline installation and management. Autoscaling adds workflow pods, not OpenShift nodes or additional disks. The configured 1-10 replicas therefore share the same single-node compute and storage resources. This layout matters when interpreting performance. File creation, reads, copies, and deletion can overlap with SQL reads, data writes, transaction-log writes, and cluster storage activity on the same disk. More pods can increase that shared I/O demand without increasing disk capacity. Storage delays can also lengthen transactions and the time locks remain held, but the topology alone does not establish that disk contention caused the measured blocking or throughput limit. How the baseline was measured The test offered small, 1 KiB files at a target rate of 100 files per second for 30 minutes. The existing workflow and database configuration were retained during the measurement; this was a baseline, not a tuned result. Measurements covered file publication, workflow starts and outcomes, execution duration, SQL request timing, SQL process resources, database-file I/O, and blocking. Existing autoscaling remained enabled, so this was not a fixed-replica benchmark. Observability also has a cost: these are instrumented results, not a claim of zero measurement overhead. SQL benchmark: reads, writes, and locking periods The database results below come from the two measured 30-minute exercises, not from the one-hour dashboard view later in this post. SQL counter snapshots bracket each exercise: approximately 1,801.16 seconds for the initial workflow-state observation and 1,801.74 seconds for the repeat. Business-data counter coverage is approximately 1,801.16 and 1,801.71 seconds. The workflow load-generation window itself is exactly 1,800 seconds. Evaluation Plain-language question What the saved measurements can answer Read How much information does SQL retrieve, and how long do disk reads take? Physical database-file read counts and average I/O latency; completed SQL request timing. Write How much information does SQL save, and how long do data and log writes take? Physical data-file and log-file write counts and average I/O latency; completed SQL request timing. Locking period How long does an operation wait for another operation, and how long does the owner hold its lock? Accumulated lock-wait time, waiting-task counts, and sampled blocking. Individual lock-hold durations were not recorded. Read and write I/O: volume and latency The two database roles are labeled workflow state and business data. Each row below describes a file-I/O operation, not an individual SQL statement. Database role / file I/O operation Initial count Repeat count Initial average ms/I/O Repeat average ms/I/O Workflow state / data Read 35,169 9,331 0.896 0.571 Workflow state / data Write 74,146 90,913 12.958 38.652 Workflow state / log Write 318,134 334,775 0.938 1.115 Business data / data Read 104 19 0.923 0.474 Business data / data Write 124 14 0.919 0.714 Business data / log Write 25,826 27,018 1.152 1.425 Average read I/O latency = read-stall milliseconds / read I/O count. Average write I/O latency = write-stall milliseconds / write I/O count. These are operation-weighted counter ratios, not averages of sample averages. The repeat performed fewer physical data reads and more workflow-state writes. Its average workflow-state data-file write latency was approximately three times the initial value. Workflow-state log writes also became slower on average. The small business-data file-I/O counts should not be treated as a stable disk-performance estimate. A read satisfied from memory need not cause a physical file read. Likewise, many row changes can be persisted together, and transaction-log writes are distinct from later data-page writes. Consequently, these counts are not SELECT counts, INSERT counts, or committed business-record counts. None of the file-I/O averages is the duration of an entire SQL statement or transaction. Completed SQL request timing SQL requests provide a separate view of elapsed server-side work. The trace selected events completed within each exact 30-minute window. Percentiles are approximate; requests still running at cutoff are excluded. Database role / request type Window Completed events Average ms p95 ms p99 ms Workflow state / remote call Initial 1,127,136 1.780 2.431 62.479 Workflow state / remote call Repeat 1,170,736 1.647 1.643 52.385 Business data / remote call Initial 81,114 0.960 1.354 14.487 Business data / remote call Repeat 84,220 1.041 1.225 15.503 Workflow state / SQL batch Initial 586 0.244 0.382 0.557 Workflow state / SQL batch Repeat 645 101.029 33.750 7,967.948 A remote call is a completed RPC event, not necessarily one statement. These request populations mix reads, writes, and supporting work; they do not establish separate SELECT-only or INSERT-only latency distributions. Batch events are shown separately rather than hidden inside the much larger remote-call population. Database-wide activity can include monitoring and dashboard requests, so this is not an application-only isolation test. The repeat improved workflow-state remote-call latency, but business-data p99 and batch latency worsened. There is no basis for saying that all SQL latency improved. Lock waiting: duration, concurrency, and observation period A lock hold belongs to the operation owning the lock: acquisition through release. A lock wait belongs to another operation waiting to obtain a conflicting lock. These are different periods; a waiting operation's duration does not reveal precisely how long the owner held the lock. Locking measurement Scope Initial Repeat Accumulated lock-wait time SQL instance 1,473.235 s 1,467.470 s Lock-waiting task count SQL instance 51,283 50,548 Wait-time / waiting-task counter ratio SQL instance 28.728 ms 29.031 ms Range/update coordination waits SQL instance 1,287.958 s 1,273.562 s Update coordination waits SQL instance 183.449 s 168.197 s Other lock waits SQL instance 1.828 s 25.711 s Peak sampled blocked requests Workflow-state database 16 20 Snapshots showing blocked requests Workflow-state database 85 / 353 78 / 354 Longest span of consecutive positive blocking snapshots Workflow-state database Approximately 15.2 s Approximately 10.2 s The cumulative lock counters are instance-wide and reported once, not added again for each database. Other activity on the instance can contribute. They count waiting SQL tasks, not unique transactions, locks, or workflow runs. The mean counter ratio is not a measured per-lock hold time or a lock-wait percentile. 1,473 accumulated wait-seconds does not mean the database was continuously blocked for 1,473 seconds. Concurrent tasks can wait at the same time. The totals cannot be divided by test duration and described as the percentage of the test spent blocked. The roughly five-second snapshots count requests blocked by another identified session. They do not record each request's wait type or lock lifetime. The longest positive-snapshot span means blocking was present at successive observations; different requests may have been involved, and blocking could have stopped between samples. It is not proof of one continuous blocking episode or one transaction holding a lock for that long. No blocked business-data requests were seen in the snapshots; brief blocking between samples remains possible. For write-related context, instance-wide waiting for transaction-log flushes accumulated 1,200.092 seconds initially and 1,390.289 seconds in the repeat. These are task-wait sums, not individual commit latency or additional time to add to workflow duration. What this does and does not establish The exercise establishes measured read/write I/O volume and average latency, mixed SQL request timing, and aggregate lock waiting with sampled blocking under the workflow workload. It does not establish isolated SQL read/write capacity, statement-specific read/write latency, exact blocking-episode lengths, or p50/p95/p99 lock-hold durations. One-hour dashboard results (Initial + repeat) These are actual values from the supplied dashboard with Last 1 hour visibly selected. This is a rolling dashboard observation, not a newly executed one-hour controlled load test. Measurement Dashboard result Selected observation period Last 1 hour Total runs displayed 45,821 Successful runs displayed 45,821 Failed runs displayed 0 Displayed successful count / 3,600 seconds 12.728 runs/second Average execution duration displayed 3.70 seconds Success rate displayed 100% Retry count No data Processing beyond the cutoff This supplied dashboard view spans a longer period than the 30-minute baseline. Processing continues after file generation stops. The displayed run total belongs to the dashboard's selected scope and aggregation. It is not the number of successful completions during the fixed measurement window, and it has not been reconciled to the exact benchmark cohort. The curve shows run counts over time, not a cumulative completion counter; its bucket size is not specified here, so the vertical values should not be read as runs per second. Latency: look beyond the average Successful workflow execution duration Result Average 4.11 seconds p50 Approximately 3.89 seconds p95 Approximately 6.20 seconds p99 Approximately 13.01 seconds Maximum 23.71 seconds These durations measure workflow execution after a run starts. They exclude time spent waiting in the receiving folder. As the backlog grows, a file's arrival-to-completion time can be much longer. Each point summarizes one minute. Workflow duration uses seconds; SQL request duration uses milliseconds. The SQL panels separate requests associated with workflow state from requests associated with business data, without exposing database identities. The first few minutes show higher workflow latency than much of the later window. The chart exposes this change but does not, by itself, establish its cause. The workflow chart includes successful runs completed by cutoff. SQL timing includes captured completed requests; requests still running at cutoff are not represented in those percentiles. Workflow bucket and whole-window comparison percentiles were computed from the observed completed runs; displayed values are rounded. SQL percentiles are approximate. SQL activity in the broader observation period These supplied SQL panels provide broader context, not additional fixed-window baseline results. SQL operations per second counts database work, not completed workflow runs: one workflow can require multiple SQL operations. The CPU line here is measured in milliseconds of SQL execution CPU time, not the percentage of host capacity shown below. Dashboard time ranges and aggregation differ from the baseline charts, so their averages and totals should not be substituted for the 30-minute measurements. SQL process measurement Result Average CPU, normalized to host capacity 1.83% Peak sampled CPU, normalized to host capacity 8.08% Physical memory at the first recorded sample Approximately 1.20 GiB Physical memory at the last recorded sample and peak Approximately 3.15 GiB These are instance-wide SQL process measurements, not workflow-container utilization or total machine utilization. CPU points represent roughly five-second interval averages, not instantaneous peaks. The dashed reference uses the reported full-window average; the recorded series ends slightly before cutoff and is not extrapolated. A system can have CPU headroom while work waits for storage, another transaction, a network response, or another part of the workflow. Aggregate CPU usage can also hide a narrower, serialized bottleneck. Configured scaling and application resources The deployment's configured scaling values were captured after the repeat. Application-configuration fingerprints matched before and after the test. Scaling setting Captured value Minimum replicas 1 Maximum replicas 10 Polling interval 30 seconds Configured cooldown 300 seconds Polling and cooldown values describe configuration, not guaranteed reaction times. Actual scaling also depends on controller decisions and stabilization. The dashboard's matching-pod count rises from about one to five, then steps down through four to three during the repeat. A later increase occurs after the measurement cutoff, while queued work continues processing. This panel counts matching pod records; it does not filter explicitly for readiness. It should not be interpreted as proof that every displayed pod was ready at every instant. Independent runtime checks found one ready replica before the repeat and three after it. The captured resource budget also distinguishes the application container from the entire pod: Resource scope, per replica CPU request CPU limit Memory request Memory limit Application container 0.425 cores 1 core 1,844 MiB 2 GiB Whole pod, including supporting containers 0.501 cores 1.5 cores 2 GiB 4.5 GiB Green represents usage; yellow represents the summed application-container limits. The chart's resource scope excludes supporting containers, so it is not the whole-pod or cluster resource budget. The CPU usage line is a five-minute rate expressed in cores. Memory usage is the containers' working set. As the number of matching application containers changes, their summed limits change too; this does not mean usage suddenly rose to the limit. These application metrics are not interchangeable with SQL process CPU percentages or SQL process physical memory. Aggregate headroom also does not exclude per-container throttling or uneven load distribution. Supplied latency dashboard This supplied panel shows p50 3.60 s, p95 5.47 s, and p99 10.5 s for its selected scope. Its time filter is not visible, so these values are not substituted for the fixed-window comparison above. Run and SQL trends beyond the repeat window This view extends beyond the 20:54:59 IST measurement cutoff and includes continued processing. Values are counts in the dashboard's time buckets, not a cumulative total or a documented runs-per-second rate. SQL duration and SQL CPU time here are in milliseconds. They are not workflow execution time or host CPU percentage. The dashboard aggregation covers a different scope from the verified 30-minute SQL measurements. How to use these results This is a baseline for one synthetic workflow, payload size, workload shape, and deployment. It is not a product-wide capacity limit, service-level guarantee, or comparison between deployment platforms. Workflow outcomes describe runs started within the measurement window and their status at cutoff. They are time-window totals, not a file-by-file correlation audit; concurrent executions of the same workflow can contribute. SQL process resources and wait measurements can include other activity on the same instance; individual SQL requests are not equivalent to workflow runs. For organizations that must keep integrations close to their data, whether for regulatory, data-residency or operational reasons, Hybrid Logic Apps brings the Logic Apps platform into their own datacenter. In this benchmark, the workflow ran fully disconnected on a single on-premises host, with SQL Server 2025 storing workflow state and no dependency on an external runtime service. The business value is straightforward. Sensitive data stays on site, workflow state lives in a database your team already operates and protects, capacity scales automatically within the hardware you own, and when demand spikes, work queues instead of failing. Teams also build on the same Logic Apps skills they use in Azure, rather than maintaining a separate integration stack for on-premises workloads. Recommendations Do not manually alter, truncate, drop, or selectively delete records from runtime-managed SQL tables. Partial changes can leave missing content, orphaned metadata, inconsistent run history, or state that affects retries and recovery. Use the deployment’s supported retention and cleanup mechanisms; any exceptional database maintenance should follow with a recoverable backup. Performance: Evaluate storage latency, CPU, memory, and blocking. Validate supported configuration changes through repeatable benchmarks rather than modifying internal tables or weakening transaction consistency. Please refer this for SQL server guidance Monitor and Tune for Performance - SQL Server | Microsoft Learn Give SQL independent I/O capacity from SMB and cluster VM storage. Increase CPU or memory when measurements justify it—not simply because throughput is low. Use supported availability groups or failover clustering for availability and recovery. These are not automatically a scale-out solution for writes. Follow Availability Group: Prerequisites, Restrictions, and Recommendations - SQL Server Always On | Microsoft Learn We executed the test using single node K8se cluster, for better use distribute workflow pods across independent worker hosts with adequate storage and networking. Scale incrementally and remeasure successful throughput, write latency, blocking, backlog, and recovery behavior while preserving runtime-managed tables.257Views0likes0CommentsModernize Any Integration Platform to Azure Logic Apps Standard with the Logic Apps Migration Agent
Explore the open-source Logic Apps Migration Agent Enterprise integration is entering a new era Enterprise integration platforms have powered business-critical processes for decades. They connect applications, data, partners, devices, and industries, often carrying transactions that an organization cannot afford to interrupt. Expectations have changed. Organizations want cloud-native architectures, AI-assisted automation, stronger governance, improved developer productivity, and faster response to business change. Yet many integration estates contain years of accumulated dependencies, custom code, transformations, operational procedures, and platform-specific knowledge. The challenge is not simply moving an orchestration or flow from one runtime to another. This is not lift and shift. It is a refactoring exercise that preserves business intent and expected behavior while translating source-platform constructs into cloud-ready workflows, connectors, code, operational patterns, and deployment practices for Azure Logic Apps Standard. That is why we created the Logic Apps Migration Agent. Introducing the Logic Apps Migration Agent: An Open-source project to provide an AI End-to-End Modernization Experience The Logic Apps Migration Agent is an open-source Visual Studio Code extension that provides an AI-assisted, end-to-end modernization experience. It uses GitHub Copilot and the Visual Studio Code Language Model API to guide teams through a structured five-stage workflow, while keeping people in control at every stage. Rather than treating modernization as a single conversion step, the agent helps teams discover what they have, understand dependencies, design an appropriate target, generate baseline implementation artifacts, validate expected behavior, and prepare the solution for deployment to Azure Logic Apps Standard. Refactor the implementation, preserve the business intent Lift and shift attempts to reproduce the source platform as closely as possible in a new environment. That approach can carry forward legacy topology, operational assumptions, platform-specific patterns, and technical debt. The Migration Agent supports a different outcome. It uses the source implementation as evidence of the required business behavior, then helps teams design and generate an appropriate Logic Apps Standard implementation. Some components may map directly, while others require restructuring, consolidation, decomposition, replacement, or custom implementation. The objective is functional and semantic continuity, not structural duplication. A successful migration should preserve contracts, transformations, routing rules, ordering requirements, error behavior, and essential business outcomes while allowing the target solution to adopt Azure-native identity, connectivity, observability, resiliency, deployment, and operating practices. Preserve what the integration must do. Refactor how it does it. Start by understanding what you have For many organizations, discovery is one of the most difficult parts of modernization. Documentation may be incomplete, original developers may no longer be available, and relationships between applications, endpoints, schemas, maps, pipelines, and custom components may be difficult to reconstruct. The Migration Agent scans the source project, catalogs supported artifacts, organizes related components into flow groups, and identifies dependencies and migration gaps. It can also generate architecture and message-flow visualizations for review before conversion begins. This discovery output becomes the foundation for migration sequencing, refactoring decisions, effort discussions, and risk management. Use AI to accelerate the work, not remove accountability The Migration Agent uses specialized GitHub Copilot agents for analysis, planning, and conversion. AI helps interpret source artifacts, propose mappings, create task plans, and generate baseline Logic Apps artifacts. Enterprise integration, however, requires more than plausible code generation. Human-in-the-loop checkpoints let teams review discovered flows, resolve missing dependencies, reshape the proposed architecture, approve conversion plans, and validate generated behavior before progressing. This combines the speed of AI assistance with the governance and technical review required for mission-critical integration. Modernize incrementally and reduce migration risk Large integration estates do not need a single big-bang program. The Migration Agent organizes work into logical flow groups so teams can refactor one business capability or integration path at a time. Prioritize workloads by business value, risk, complexity, or platform urgency. Validate target architecture and operating patterns with a representative first migration. Run phased cutovers and coexistence strategies when required. Apply reusable refactoring patterns, templates, and engineering standards to subsequent waves. A phased approach helps teams build experience with Azure Logic Apps while reducing migration risk and preserving delivery momentum. Bring your own tests and validate continuously Migration confidence depends on behavior, not structural similarity. The agent supports validation using source specifications, sample files, test cases, and customer-provided black-box tests. This helps compare expected inputs and outputs and identify semantic differences earlier. Generated artifacts are a baseline. Domain-specific transformations, error-handling behavior, performance characteristics, security controls, and edge cases still require customer and partner expertise. Built for BizTalk today and extensible for other platforms BizTalk Server 2016 and BizTalk Server 2020 are the first fully implemented source platforms. MuleSoft Anypoint support is represented as an in-progress built-in parser. The architecture is open and extensible so contributors can add parsers and platform-specific migration capabilities for other integration technologies. That extensibility is central to the vision. A common modernization workflow can help teams apply consistent governance, target patterns, refactoring practices, and validation across mixed integration estates. Why Azure Logic Apps Standard? Azure Logic Apps Standard provides a modern destination with a local project structure, Visual Studio Code development experience, source-control alignment, CI/CD support, stateful and stateless workflows, enterprise connectivity, and Azure and hybrid deployment options. Modernization is not about reproducing a legacy topology component by component. The target design should be optimized for Logic Apps Standard rather than constrained by the source architecture. The migration preserves valuable business logic while refactoring the implementation around modern practices for identity, networking, observability, reliability, deployment, and operations. What your team should still own The Migration Agent accelerates repeatable work, but it does not replace the decisions that define a production-ready integration platform. Responsibility Refactoring focus Target architecture Refactor application and workflow boundaries for Logic Apps Standard. Select reliability, networking, deployment, and supporting Azure patterns rather than copying the source topology. Semantic equivalence Validate contracts, mappings, transformations, business rules, error behavior, ordering, retries, and edge cases. Capability gaps Redesign source capabilities without direct equivalents using connectors, custom code, local functions, API Management, Service Bus, or other appropriate Azure patterns. Production hardening Implement identity, secrets management, security policies, monitoring, cost controls, performance testing, resiliency, and operational ownership. Cutover and coexistence Plan backlog reconciliation, dual-run periods, data consistency, partner coordination, rollback, and decommissioning. More mission critical features for Logic Apps Standard and Hybrid We are weeks away from shipping the following features, aimed at any customers in the Enterprise Application Integration space: HL7 In-App operations in general availability. MLLP Receive/Send In-App connector in Public Preview. Rules Engine In-App operation for XML facts in Public Preview. MSMQ In-App connector in Public Preview. Oracle DB In-App connector in Public Preview. Flat File generation In-App operations in Public Preview. Integration accounts support (Hybrid On premises). NMS In-App connector in Public Preview. Improvements to our EDI capabilities. BizTalk Mapper to Data Mapper Migration path What about other integration platforms? Yes—the Logic Apps Migration Agent is designed to be customizable so you can migrate from any integration platform to Logic Apps (not just BizTalk). The open architecture lets you plug in new discovery, analysis, and conversion skills for the source product you’re modernizing, while keeping the same stage-gated workflow and human-in-the-loop checkpoints. We provide guidance and examples to help you extend the agent for other platforms than BizTalk —so you can tailor mappings, transformation rules, and validation to your customer’s standards and target patterns in Logic Apps. Benefits Faster time to value with a guided process: A structured discovery→planning→conversion workflow reduces uncertainty and helps teams move from assessment to execution with clear checkpoints. Higher confidence migrations: Human-in-the-loop validation, artifacts generation, and black-box testing support mission‑critical correctness and governance. Customizable for your source platform and standards: Extend the agent with product-specific discovery and conversion steps, tailor mappings and transformation rules, and align outputs with your target Logic Apps patterns and engineering conventions. Open-source transparency and control: Review how the tool works end-to-end, validate what it produces, and adopt changes at your pace without waiting for a closed release cycle. Community-driven innovation: Benefit from contributions across Microsoft, partners, and customers—new adapters, mapping packs, and best practices can be shared and reused. Lower total migration cost: Automating repeatable tasks reduces manual effort while preserving the ability to invest partner expertise where it matters most (architecture, governance, reliability, and operations). Reusable accelerators for partners: Partners can create differentiated offerings by packaging templates, validation suites, CI/CD pipelines, and domain-specific patterns on top of the agent. An accelerator for customers and partners For customers, the Migration Agent provides a practical starting point and a consistent process for moving from assessment to a refactored implementation. For professional services organizations and system integrators, the agent augments delivery rather than replacing it. Automating inventory, analysis, baseline generation, and validation scaffolding allows experts to focus on architecture, governance, security, reliability, domain-specific transformation, DevOps, performance, cutover, and operating-model change. Because the project is open source, partners can contribute parsers or package reusable templates, mapping packs, test suites, CI/CD assets, and industry-specific modernization patterns. Review our public documentation here: https://learn.microsoft.com/en-us/azure/logic-apps/migration/migration-agent-overview How to get started Download VSCode and install the Logic Apps Migration Agent extension. Organize source projects and dependencies in a clear directory structure. Include project files, bindings, schemas, maps, pipelines, orchestrations, custom code, configuration, certificates or certificate references, and available documentation. Once you have all your artifacts ready, point the Migration Agent to the directory with all the artifacts. Review every migration stage. Confirm the discovered architecture, resolve missing dependencies, and refine the target design before authorizing conversion. Prepare a representative test environment. The workstation running Visual Studio Code must be able to reach the systems needed for local or end-to-end validation. Bring known inputs, expected outputs, specifications, and existing test cases whenever possible. These materials improve validation and reduce ambiguity. Treat the first migration as a reusable foundation. Capture architecture patterns, naming standards, deployment templates, observability practices, and lessons that can accelerate subsequent waves. Use Claude Opus 4.8 or higher. Make sure you increase the Maximum number of requests for the Copilot Chat as follows (we recommend changing the value from 60 to 1000) Check the following video for a demonstration on how the Agent works and let us know if you have any questions in the comments.2.6KViews2likes1Comment💲Announcing Free Grant and Pricing for Logic Apps Automation
Today, we're announcing pricing for Azure Logic Apps Automation, now in public preview, along with monthly free grants that make it easier to start building, experimenting, and bringing automations to life. Logic Apps Automation is Azure's fully managed platform for business process automation and orchestration, including AI-powered automation. It's built for every builder with an automation problem, not just developers, and the free grants make it easy to go from idea to a working automation without a purchase decision up front. The free grant covers one managed environment per subscription and includes usage across key Logic Apps Automation capabilities, so you can start with your first use case, experiment with AI-powered automation, and run workloads in production within the included limits; then move to paid usage as your needs grow. Start today @ https://auto.azure.com/ Start free with monthly grants Every Azure subscription gets a monthly free grant across the platform. The only exception is Managed Environment which is a one-time free grant for first 60 days. When the usage stays within these limits you pay nothing. When it goes beyond these limits, you pay only for the additional usage. Usage Component Monthly free grant (per subscription) Core Platform Managed environment One environment, free for the first 60 days (2 months) Core Platform Workflow runtime 108,000 execution-seconds (about 30 hours) Core Platform Data retention 1 GB Optional Capabilities Managed connector calls 1,000 Standard + 500 Enterprise Optional Capabilities Knowledge storage 1 GB Optional Capabilities AI usage 1,100 AACs Optional Capabilities Isolated code execution 18,000 seconds (about 5 hours) What this means in practice Explore the platform, not a trimmed-down experience. The grants include workflow runtime, AI usage, knowledge, connectors, and sandboxed code, so you can explore every capability from day one. Build and iterate without watching the meter. With approximately 30 hours of execution time included each month, you can author, test, and run workflows as you build out your automation. Scale into paid usage as your needs grow. Grants reset every month, and you pay only for usage beyond them. Simple, usage-based pricing Beyond the included grants, Logic Apps Automation uses a pay-as-you-go pricing model across the capabilities your automations use. Billing has two parts: Core Platform: the managed environment, workflow runtime, and run-history retention that provide the foundation for your automations. Optional Capabilities: AI usage, knowledge storage, isolated code execution via sandbox and managed connectors, billed only when your workflows use them. For rates, regional pricing, and a worked monthly cost example, see Azure Logic Apps Automation pricing. How does the free grant works The free grant applies to the first environment you create in a subscription. Look for the Free tag next to an environment's name to see which is the free one Free environment period: The managed environment is free for 60 days, starting from the time you create it. Existing customers: If you already use Logic Apps Automation, create a new environment to use the free grant. The first new environment you create in your subscription receives it. Track your usage: In your environment, go to Settings and select the Free Grants tab to see your monthly limits and how much you've used. Important: Free grants are tied to the free environment. If you delete your free environment, you lose the ability to use the free grants, and you can't get them back by creating a new environment. Availability Logic Apps Automation is in public preview in Australia East, East Asia, North Central US, Southeast Asia, Sweden Central, UK South, and West US. Preview pricing and availability may change before general availability. Get started If you already have an Azure subscription, your included grants are available to help you start building today. Create your first Automation project, start from a template or with the AI workflow assistant, and explore what you can build with Logic Apps Automation. Get started with Logic Apps Automation Quickstart: build your first workflow Read the full pricing details MS Learn documentation Watch the Logic Apps Automation video series Share feedback or request a feature, or just let us know what you build with Automation!749Views0likes0CommentsFrom Form to Action: A Governed, Event-Driven AI Intake Pipeline with Azure Integration Services
A production-minded reference architecture using Azure Integration Services and Microsoft Foundry to turn document-heavy intake into governed, traceable work. TL;DR: Calling a model is one step in AI-powered intake. Production readiness depends on everything around the model: authenticated entry, controlled model consumption, durable asynchronous processing, explicit failure handling, and one correlation ID carried from the gateway to the final event. This post walks through a permit-intake reference architecture on Azure Integration Services and a companion repository you can run offline, without an Azure subscription. The Problem: Intake is where AI Prototypes Stall Many teams have built an AI prototype that reads a scanned form, extracts the key fields, and returns clean, structured data. That prototype proves the model can do the job. Taking it to production raises a different set of questions: Who is allowed to call this, and how many times per minute? What happens when the model returns a 429 or the CRM is down for maintenance? Which team consumed those tokens? Can you show me everything that happened to application #00417? Who is notified when a record is created, and what breaks when we add another subscriber? None of those questions is about the model, yet each one can decide whether the solution ships. The underlying customer problem is broader than “How do we read a form?” It’s “How do we accept responsibility for a submission, process it reliably across slow or unavailable dependencies, and give applicants and operators a trustworthy status?” That framing moves the design from a single AI call to a governed system of connected services. In this post, I use a fictional county’s building-permit intake as the running example. A resident submits a permit packet, and the county needs to validate it, extract the key fields, score it against intake policy, record it in a case system, and notify the right people, with a complete audit trail. The same shape appears in insurance first notice of loss, benefits enrollment, supplier onboarding, and claims intake. The repository keeps the domain in schemas and configuration: replace the schemas and labels, and keep the boundaries. My thesis is simple: the hard part of production AI intake is connecting the services around the model reliably and under governance, not calling the model. The model is one component of the system. It isn’t the system. Scope note: This is a production-minded reference architecture, not a production-ready template. The people, permit data, identifiers, and URLs in this post are synthetic, and the screenshots and trace rows show only that synthetic data. The repository favors demonstration clarity: public endpoints, simple SKUs, and simulated fallbacks. Architecture at a Glance Figure 1. The governed, event-driven permit-intake flow. One correlation ID follows the permit from the gateway to the published event. The design separates the acceptance path from the processing path. API Management owns the caller-facing contract and hands the work to a queue. Slow or failure-prone work happens after that hand-off. The flow reads left to right: Portal → API Management → Logic App → Service Bus → Function → Case system → Event Grid → Subscribers │ Document Intelligence + Foundry model (through the AI gateway) Responsibility Service Why this service Governed front door and AI gateway Azure API Management One policy boundary for business APIs and model APIs Low-code validation, enrichment, and routing Azure Logic Apps Business-visible run history; easy to change routing rules Durable hand-off and back-pressure Azure Service Bus Retries, duplicate detection, and dead-lettering Processing worker Azure Functions Scales with queue depth; runs the shared orchestrator Field extraction Azure Document Intelligence Layout and key-value extraction from the packet Policy-oriented scoring Azure OpenAI in Microsoft Foundry Models Rubric-based completeness and consistency review Fan-out to downstream consumers Azure Event Grid Decoupled subscribers via CloudEvents One correlation ID across the flow Application Insights End-to-end transactions plus one KQL join Discovery and reuse Azure API Center A catalog of the Permits and model APIs The case-system box is deliberately not a CRM product. The repository’s crm.py is an adapter: an in-memory stub by default, or an HTTP call to whatever CRM_BASE points at. Swap in Dynamics 365 or your records system without changing the orchestration contract. Let’s walk through the design decisions that matter most. API Management is more than a Proxy API Management is often introduced as a proxy. In this architecture, it’s the governance boundary, and it governs two surfaces. Figure 2. One gateway governs both the business API and the model API. Surface 1: The Permits API The Entra-protected variant of the inbound policy (permits-api.policy.xml, abridged) authenticates, throttles, and stamps a correlation ID before any backend code runs: <inbound> <base /> <validate-azure-ad-token tenant-id="{{tenant-id}}" failed-validation-httpcode="401"> <audiences><audience>api://ais-demo-permits</audience></audiences> </validate-azure-ad-token> <rate-limit-by-key calls="60" renewal-period="60" counter-key="@(context.Subscription?.Key ?? context.Request.IpAddress)" /> <set-variable name="correlationId" value="@(context.Request.Headers.GetValueOrDefault("X-Correlation-Id", Guid.NewGuid().ToString()))" /> <set-header name="X-Correlation-Id" exists-action="override"> <value>@((string)context.Variables["correlationId"])</value> </set-header> <set-backend-service backend-id="permit-intake-logicapp" /> </inbound> Three lines of intent are worth calling out: validate-azure-ad-token rejects missing, invalid, or expired Microsoft Entra tokens with a 401 at the edge, so unauthenticated requests are rejected before they reach the backend. It knows the Entra issuers and signing keys for your tenant, so there’s no OpenID configuration URL to maintain. rate-limit-by-key gives each consumer its own budget and returns 429 with Retry-After when it’s exceeded. The correlation ID is created here (or accepted from a trusted caller) and echoed back on the 202 Accepted response. That single value is how you’ll find this permit later. The deployed demo authenticates callers with API Management subscription keys and applies the same rate limit and correlation ID. To adopt the Entra variant, register an app for the api://ais-demo-permits audience, register a backend for the Logic App trigger, and then swap the policy. Surface 2: The Model API (The AI Gateway) The Function doesn’t call the model endpoint directly. It calls the Azure OpenAI v1 API through API Management, where a second policy applies (abridged): <inbound> <base /> <llm-content-safety backend-id="content-safety-backend" shield-prompt="true"> <categories output-type="EightSeverityLevels"> <category name="Hate" threshold="4" /> <category name="SelfHarm" threshold="4" /> <category name="Sexual" threshold="4" /> <category name="Violence" threshold="4" /> </categories> </llm-content-safety> <llm-token-limit counter-key="@(context.Subscription?.Id ?? "anonymous")" tokens-per-minute="20000" token-quota="2000000" token-quota-period="Monthly" estimate-prompt-tokens="false" /> <llm-emit-token-metric namespace="ais-demo-ai-gateway"> <dimension name="Subscription" value="@(context.Subscription?.Name ?? "unknown")" /> <dimension name="Department" value="@(context.Request.Headers.GetValueOrDefault("x-dept", "unknown"))" /> </llm-emit-token-metric> <set-header name="api-key" exists-action="delete" /> <authentication-managed-identity resource="https://cognitiveservices.azure.com" /> <set-backend-service backend-id="foundry-models-backend" /> </inbound> In order, that policy: llm-content-safety sends the prompt to Azure AI Content Safety, with Prompt Shields for injection attempts, and returns 403 for prompts that exceed the configured thresholds, before they reach the model. llm-token-limit gives each consumer a tokens-per-minute budget (429) and a monthly token quota (403). llm-emit-token-metric publishes token usage to Application Insights with a department dimension for showback or chargeback. Managed identity authenticates the gateway to the model. The caller’s API Management subscription key is stripped, and local (key) auth is disabled on the Foundry resource, so the Function doesn’t hold a model key, which helps reduce the risk of key leakage. The backend also has a circuit breaker that trips after three 429 or 5xx responses within a minute, pauses calls for a minute (or for the Retry-After period the model returns), and then resumes. The repository includes sample KQL for token monitoring and chargeback views. The key point: conventional APIs and AI endpoints share one governed boundary. Your security team reviews one set of policies, and your platform team gets one place to see who is calling what. Discovery: Azure API Center API Management governs runtime traffic; Azure API Center is where people find the APIs. The repository links API Center to API Management, so the Permits APIs and the model API are cataloged with their definitions, lifecycle stage, and environment. Before a team builds another intake API or model proxy, they search the catalog and still call API Management at runtime. API Center isn’t on the request path. Why the Flow is Asynchronous The Permits API returns 202 Accepted with a correlation ID. It doesn’t wait for extraction, scoring, or the case system. That’s deliberate: document analysis, model calls, record writes, and notifications all have different latency and failure behavior, and holding the caller’s request open couples the caller to each of them. Governance boundary: 202 means the platform durably accepted responsibility for the permit. It doesn’t mean extraction succeeded, a model approved anything, or a record was committed. The repository enforces that literally. On the direct route (POST /permits), API Management writes to Service Bus and checks the answer before it says yes: <send-request mode="new" response-variable-name="sbresponse" timeout="20" ignore-error="true"> <!-- POST to https://{namespace}.servicebus.windows.net/permits-in/messages with managed identity --> </send-request> <choose> <when condition="@(context.Variables.GetValueOrDefault<IResponse>("sbresponse") == null || context.Variables.GetValueOrDefault<IResponse>("sbresponse").StatusCode != 201)"> <return-response> <set-status code="503" reason="Service Unavailable" /> <!-- plus Retry-After --> </return-response> </when> </choose> <!-- only now: return 202 Accepted with X-Correlation-Id --> If Service Bus doesn’t confirm the write (an error status, a timeout, or no connection), the caller gets 503 with Retry-After, not a 202 for work that wasn’t queued. Logic Apps: Validate, Enrich, Route The Logic App workflow checks the payload, attaches the correlation ID, and hands the message to Service Bus with its own managed identity. If required fields are missing, it returns 400 immediately. Here’s the send step: "Send_to_Service_Bus": { "type": "Http", "inputs": { "method": "POST", "uri": "https://@{parameters('serviceBusNamespace')}.servicebus.windows.net/@{parameters('permitsQueue')}/messages", "headers": { "BrokerProperties": "@{string(outputs('Broker_properties'))}" }, "body": "@outputs('Enrich_message')", "authentication": { "type": "ManagedServiceIdentity", "audience": "https://servicebus.azure.net" } } } A preceding Broker_properties step sets MessageId to the parcel number and CorrelationId to the request’s correlation ID. Bicep loads this same workflow JSON when it deploys the Logic App, so each deployment applies the workflow definition from the repository. Business analysts can read the run history in the Azure portal. If the county adds a new permit type or a routing rule, that change happens in the workflow, not in Python. Design choice: The template deploys both routes. POST /permits-orchestrated goes through this Logic App. POST /permits uses a direct-enqueue policy that writes straight to Service Bus with the API Management managed identity; it’s the portal’s default and the route the trace below uses. Use the direct route when you don’t need low-code enrichment. Keep the Logic App when business users own the routing rules. Service Bus: The Durable Hand-off The permits-in queue is configured in Bicep with: maxDeliveryCount: 5, a message is delivered up to five times (the first attempt plus four retries) before it’s moved to the dead-letter subqueue. requiresDuplicateDetection: true with a 10-minute window, resubmitting the same messageId (the parcel number) doesn’t create a second message. See duplicate detection. deadLetteringOnMessageExpiration: true, expired messages are kept for inspection instead of being dropped. Functions: One Orchestrator, Many Hosts A Service Bus–triggered Function (Python 3.14 on Flex Consumption) reads the correlation ID from the message properties and runs a framework-agnostic orchestrator. A message without a permit type raises an error, so Service Bus retries it and then moves it to the dead-letter queue. The orchestrator does four things in order: extract → score → record → publish. def process_permit(permit: dict, correlation_id: str) -> ProcessResult: extracted = document_intelligence.extract_fields(permit) # Document Intelligence compliance = ai_gateway.score_compliance(extracted) # model via the API Management AI gateway status = "IntakeReview" if compliance.score >= settings.compliance_threshold else "NeedsAttention" permit_id = crm.create_permit_record(extracted, compliance, correlation_id, status) event_grid.publish_permit_created(PermitEvent(permitId=permit_id, complianceScore=compliance.score, correlationId=correlation_id)) ... Notice what the model doesn’t do: it doesn’t approve or deny anything. The score (0–100, against a rubric for completeness, consistency, and policy fit) only decides which human review state the permit lands in, IntakeReview or NeedsAttention, and that state is written to the case record. The call uses the Responses API on gpt-5.4-mini with structured output: the response must match a JSON schema (score, missing, flags), so downstream code receives a consistent, schema-validated shape. There’s no dated api-version to maintain: client = OpenAI( base_url=f"{apim_base}/openai/v1/", api_key=subscription_key, default_headers={"api-key": subscription_key, "x-dept": "permitting"}, ) review = client.responses.parse( model="gpt-5.4-mini", instructions=RUBRIC, input=fields_json, text_format=Review, reasoning={"effort": "low"}, store=False, ).output_parsed The caller authenticates to API Management, not to the model: the api-key header carries the caller’s API Management subscription key (the template renames this API’s subscription-key header to api-key). The OpenAI client requires api_key and also sends it as a bearer token, but the gateway replaces that header with its own managed-identity token before calling the model. For production, swap the subscription key for a Microsoft Entra token (api_key=token_provider) and validate it at the gateway. The same process_permit function is hosted by the Function, by a FastAPI service for the portal, and by the Python SDK walkthrough. That keeps the demo, the tests, and the deployed worker running the same code. Event Grid: Fan-out without Coupling After the CRM write, the Function publishes a PermitCreated CloudEvent. Two subscribers react independently: an analytics/audit queue and, when you supply a webhook URL, a resident notification webhook. Each subscription makes up to 30 delivery attempts over 24 hours. Adding a third subscriber, such as a GIS update or an inspector scheduling system, is a new subscription. It’s not a change to the permit flow. Commands and Events are Different Things Service Bus carries a command: “process this permit.” Event Grid carries a fact: “this permit was created,” published only after the record write succeeds. Keeping them separate makes retries, ownership, and subscriber behavior easier to reason about, a poison message can be retried and dead-lettered without a PermitCreated event going out for work that didn’t finish. Four rules follow: Message identity: a stable message ID (the parcel number) and the correlation ID as a message property. In the repository. Idempotency: a redelivered message must confirm earlier work, not create a duplicate record. Production work. Dead-letter ownership: someone watches the queue, reads the reason codes, and is authorized to replay. Operational. Status: callers need a status resource (accepted, processing, needs review, completed, failed) that doesn’t expose document contents. Production works the repository returns only the correlation ID. How Failures are Handled and What Still Needs Work A production-minded design makes failure behavior explicit before the happy path is trusted. The table separates what the repository does today from what still belongs on the production path: Failure What happens in the repository Still needed for production Caller has no valid token 401 at API Management (Entra policy variant); no backend call Entra validation on every public API Caller exceeds its rate limit 429 with Retry-After Per-consumer products and quotas Payload missing required fields Orchestrated route: 400 from the Logic App, passed back by API Management. Direct route: accepted, then dead-lettered by the Function if type is missing The same validation on the direct route Queue unavailable Direct route: 503 with Retry-After. Orchestrated route: the Logic App run fails and returns an error. Neither returns 202 An alert on enqueue failures Malformed message on the queue Delivered up to five times, then dead-lettered (MaxDeliveryCountExceeded) A named owner and a replay procedure Prompt blocked by content safety, or monthly token quota spent 403 from the gateway; Service Bus redelivers the message, then dead-letters it Route to NeedsAttention with a reason instead of dead-lettering Model unavailable (429 or 5xx from the gateway or model) The OpenAI client retries twice, then Service Bus redelivers the message and finally dead-letters it. The backend circuit breaker pauses calls to the model while it’s tripped Route to NeedsAttention with the reason model_unavailable, keeping the deterministic validation results Case system unavailable The Function fails before publishing; the message is redelivered An idempotency key on the record write Event Grid unavailable after the record write The Function fails; a retry can repeat the record write A transactional outbox for the event A notification subscriber is down Event Grid retries that subscriber only (30 attempts over 24 hours) — Two rows deserve a closer look. Model unavailable: today, a model failure retries and then dead-letters the permit. A better design keeps the deterministic validation results, routes the permit to NeedsAttention with a reason such as model_unavailable, and never treats a missing score as approval. Case system unavailable: the record write is the commit point for PermitCreated, so the event must never go out before it. Idempotency keys plus an outbox let a committed record and its event be reconciled. A prototype doesn’t need these safeguards; a production service does. AI is Optional and Bounded The non-AI capabilities like durable acceptance, extraction, deterministic validation, the case record, and events are useful with generative AI turned off. The model’s score is advisory: it prioritizes review and surfaces gaps. It must never quietly become the approval decision. Extraction output is evidence to validate, not ground truth. Deterministic rules own required fields, allowed values, and hard policy constraints. In the repository, the Logic App rejects a packet without name or type, and the Function dead-letters a message without type. The model doesn’t enforce either rule. The model’s output is schema-constrained (score, missing, flags) and labeled advisory. Low scores, conflicting evidence, and model failures route to people. Logs carry identifiers and stage outcomes, not document bodies. Before any real workload, evaluate the scorer in Microsoft Foundry with synthetic or properly governed labeled data. The scorer is a direct model call through API Management, not a Foundry agent, so use dataset-based evaluators and graders, and keep an authorized person in the loop for consequential decisions. Trace One Permit End to End Governance is only useful if you can prove what happened. Here’s one synthetic permit created through the demo environment. Submit. The client posts the permit to API Management: { "name": "[Applicant Name]", "type": "Building", "parcel": "AIS-TT-102242", "applicantEmail": "[Applicant Email]" } Govern and accept durably. On the direct /permits route, API Management applies its policies, stamps a correlation ID, writes the message to permits-in, and only after Service Bus answers 201, returns 202 Accepted with X-Correlation-Id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx. Process. The Function picks up the message and extracts the fields. This run had no document attached, so it used the repository’s synthetic extraction fallback; attach a document URL to exercise Document Intelligence. Score, behind content safety. The Function calls the model through the AI gateway. Content Safety and Prompt Shields screen the prompt first; then gpt-5.4-mini returns a score of 22 and lists missing applicant contact details and a project description. Status: NeedsAttention, which is the expected result for a packet missing those details. (Simulated mode scores the same packet 100.) Record and publish. The case-system adapter creates P-E6980B0C, and the Function publishes PermitCreated; Event Grid delivers it to the analytics queue. Reconstruct. One query returns the whole journey. The portal shows the same journey to a business audience: Figure 3. The portal’s processing result and hop-by-hop trace. This screenshot is from simulated mode, so all values are synthetic and the applicant is shown as a placeholder. In Application Insights the journey is two operations. The intake operation is the API Management request and its Service Bus write. The processing operation is one end-to-end transaction: the Function, its call back through the AI gateway, the Content Safety checks, the model call, and the Event Grid publish. The Service Bus hop doesn’t carry W3C trace context, so the correlation ID is the join key, API Management logs it as a header, and the Function’s log lines name it. This query finds the operations that mention it: let cid = '<correlation-id>'; let hits = union AppRequests, AppDependencies, AppTraces, AppExceptions | where OperationId == cid or Message has cid or tostring(Properties) has cid; let ops = hits | where isnotempty(OperationId) and OperationId != '00000000000000000000000000000000' | distinct OperationId; union (union AppRequests, AppDependencies, AppExceptions | where OperationId in (ops)), (hits | where Type == 'AppTraces') | project TimeGenerated, Type, Name = coalesce(Name, Message, OuterMessage), ResultCode, DurationMs, AppRoleName | order by TimeGenerated asc For the permit above, it returned: Operation Hop Component Result Duration (ms) Intake POST /permits API Management 202 1,471 Intake POST /permits-in/messages Service Bus enqueue 201 177 Processing ServiceBusProcessor.ProcessMessage Azure Functions — 5,875 Processing POST /openai/v1/responses AI gateway (called by the Function) 200 4,542 Processing POST /contentsafety/text:analyze Content Safety 200 777 Processing POST /contentsafety/text:shieldPrompt Prompt Shields 200 235 Processing POST /openai/v1/responses Foundry model (gpt-5.4-mini) 200 2,705 Processing POST /api/events Event Grid publish 200 83 Durations come from one run in a demo environment, including cold starts. They aren’t performance figures. Figure 4. The processing operation for the same permit in Application Insights. The durations match the table above. Resource names and tenant identifiers are redacted. When a caseworker asks, “What happened to application #00417?”, the answer can come from one query instead of separate log searches across teams. Run it Locally, then Deploy it The repository is designed so you can understand the architecture before you spend anything on Azure. 1. Offline Simulation (no Azure Subscription) uv sync --extra dev # Python 3.14 cp .env.example .env # SIMULATED_MODE=true by default uv run ais-demo # runs steps B1–B8 end to end In simulated mode, each adapter (Service Bus, Document Intelligence, the model, CRM, Event Grid, Azure Monitor) is replaced by an in-memory stand-in with the same interface. The walkthrough submits a permit, enqueues it, extracts and scores it, writes the record, publishes the event, dead-letters a deliberately malformed message, and prints the correlated trace. The test suite (uv run pytest) covers the same paths. To see the business view, start the API and portal together: ./scripts/setup.sh ./scripts/app.sh start # API on :8000, portal on :5173 (Node.js 24 LTS) 2. Same Interface, Azure-backed Adapters Each adapter module checks one setting: if settings.simulated_mode or not settings.servicebus_fqdn: return _consume_simulated(handler) return _consume_live(handler, settings) # azure-servicebus + DefaultAzureCredential Set SIMULATED_MODE=false, provide the endpoints, and the same orchestrator talks to real services. Live adapters authenticate with DefaultAzureCredential, so the deployed Function uses its managed identity for Service Bus, Document Intelligence, Event Grid, and Azure Monitor. Both Python hosts export OpenTelemetry to Application Insights, and the Function’s log lines name the correlation ID. 3. Deploy with Bicep and Clean up az group create -n rg-ais-demo -l eastus2 az deployment group what-if -g rg-ais-demo \ --template-file infra/main.bicep --parameters infra/main.bicepparam az deployment group create -g rg-ais-demo \ --template-file infra/main.bicep --parameters infra/main.bicepparam # or: azd provision --preview && azd provision One deployment creates and wires the whole stack: Service Bus and Event Grid (with the analytics subscription, plus the notification webhook subscription when you pass notificationWebhookUrl), Document Intelligence, a Microsoft Foundry resource with the gpt-5.4-mini deployment, the Logic App workflow, a Flex Consumption Function App on Python 3.14, API Management with all three APIs (/permits, /permits-orchestrated, and /openai) and their policies, API Center, and the managed-identity role assignments it needs. Local (key) auth is disabled on Service Bus, Event Grid, Document Intelligence, and the Foundry resource. The template defaults to the BasicV2 tier of API Management; the sample main.bicepparam sets the classic Developer tier to match the existing demo environment, so change apimSku for a new environment. For a faster inner loop, pass deployApim=false. After provisioning, publish the Function code; the deployment guide has the details, and a GitHub Actions workflow runs the same what-if and provision steps with OpenID Connect. When you’re done: az group delete -n rg-ais-demo --yes --no-wait The repository also includes a demo track that tells the same story two ways: an Azure portal click-through for business stakeholders (steps A1–A15) and a Python SDK walkthrough for engineers (steps B1–B8). Production Boundaries: What this Reference doesn’t Do This repository is a production-minded reference architecture: it anticipates production concerns while staying candid about what it doesn’t prove. A production path starts from your organization’s requirements and platform standards. Here’s the gap: Area In the repository Before production Networking Public endpoints Private endpoints, virtual network integration, and a WAF in front of internal API Management (reference architecture) Identity Managed identity to Service Bus, Event Grid, Document Intelligence, and the Foundry resource, with local auth disabled; API Management subscription keys for callers (an Entra token policy is provided) Microsoft Entra token validation on every public API; the Function’s API Management subscription key in Key Vault or replaced by Entra auth AI safety Content Safety and Prompt Shields at the gateway; structured output; advisory-only scoring Tuned thresholds and blocklists, response-side checks, and offline and continuous evaluation gated in CI Data retention In-memory or simulated CRM A real system of record with retention, residency, and deletion policies agreed with records owners Consistency Retries, duplicate detection, and dead-lettering Idempotency keys and an outbox for the record write and event publish Caller status The correlation ID A status resource (accepted, processing, needs review, completed, failed) Access control One demo subscription Per-consumer products, least-privilege RBAC, and separated duties for operators and reviewers Operational ownership Demo scripts Dashboards, alerts on dead-letter depth and token budgets, runbooks, and named owners for every queue Human review Score routes to a review state Documented reviewer workflow, override capture, and periodic sampling of AI-assisted decisions Figure 5. The same services in a network-isolated API Management landing zone. The repository’s production path maps each of these items to the Azure Well-Architected Framework pillars. It also sketches how the AI gateway grows into a multi-region front door with backend pools, circuit breakers, and semantic caching, without changing the governance policies you already have. Map the Article to the Repository Article Repository location Shared pipeline src/ais_demo/orchestrator.py Governed intake (direct, orchestrated, Entra variant) apim/policies/permits-api*.xml AI gateway apim/policies/aoai-api.policy.xml Logic App workflow integration/logicapp/permit-intake-workflow.json Durable command and dead-lettering src/ais_demo/integrations/service_bus.py Extraction src/ais_demo/integrations/document_intelligence.py Advisory scoring src/ais_demo/integrations/ai_gateway.py Case-system adapter src/ais_demo/integrations/crm.py Events src/ais_demo/integrations/event_grid.py Trace join src/ais_demo/integrations/monitor.py Infrastructure infra/main.bicep and infra/modules/ Runbooks docs/deployment-guide.md and docs/demo-track.md Production path docs/production-path.md Key Takeaways Put the model behind the same gateway as your APIs. Content safety, token limits, usage metrics, and managed identity help turn model access into something you can govern and attribute. Accept fast, process durably and mean it. Return 202 only after the queue confirms the message. That helps shield residents from downstream outages and gives operators a dead-letter queue to inspect instead of a lost request. Keep AI advisory. Let the model route work to people. Don’t let it make the decision. Create one correlation ID at the edge and carry it through each hop. It’s one of the simplest audit trails you can build. Decouple what happens next. Event Grid lets new consumers subscribe without touching the intake flow. What to do Next Agree on the acceptance contract: exactly when 202 is returned and how callers check status. Run the simulated portal and Python walkthroughs with one synthetic correlation ID. Test the failure paths: queue unavailable, poison message, model unavailable, case system unavailable, and a trace gap. Add idempotent record writes and an outbox for event publication. Evaluate the advisory model separately from deterministic rules and human approval. Complete an architecture, privacy, security, and Well-Architected review for your subscription before using real data. Try It Repository: github.com/honestypugh2/ais-demo. Start with uv run ais-demo, no Azure subscription required. Adapt it: Change the schemas in src/ais_demo/schemas/permit.py, update USE_CASE_PROFILE and the samples in data/, and keep the topology. Go deeper: AI gateway capabilities in API Management · Service Bus dead-letter queues · Event-driven architecture style · Investigate transactions in Application Insights Related reading: Grounding Copilot Studio Agents with Azure AI Search and Foundry IQ Models will change. The work around them is what moves intake from form to action: a governed front door, durable hand-offs, advisory scoring, and one correlation ID from submission to the final event. Clone the repository, run it offline, and adapt the schemas to your own intake process. Comments and questions are welcome below. The sample code in this post and the companion repository is provided "as is" under the MIT license for demonstration purposes. It uses synthetic data only and isn't intended for production use without additional security, reliability, and compliance review. Nothing in this post is legal, compliance, security, or deployment assurance, and it doesn't represent a customer implementation. The county and applicant in this example are fictional. Check product availability, quotas, model access, and regional capabilities for your own subscription.625Views0likes0CommentsLogic Apps Aviators Newsletter - October 2026
In this issue: Ace Aviator of the Month News from our product group News from our community Ace Aviator of the Month October 2026's Ace Aviator: Hicham Boutaleb & Azure Solution Architect @ 5-Nines Consulting What's your role and title? What are your responsibilities? I work as an Enterprise Integration Architect, helping organizations design, implement, and modernize integration platforms using Microsoft technologies. My responsibilities include defining architecture, leading technical delivery, supporting development teams, ensuring best practices around security and governance, and helping customers get the most value from Azure services such as Logic Apps, API Management, Service Bus, and Azure Functions. Can you give us some insights into your day-to-day activities and what a typical day in your role looks like? No two days are exactly the same, which is one of the things I enjoy most about my role. A typical day usually involves a mix of: - Designing integration and automation solutions. - Reviewing architectures and code with project teams. - Supporting customers in solving complex technical challenges. - Running workshops and knowledge-sharing sessions. - Evaluating new Azure capabilities and how they can benefit ongoing projects. - Collaborating with business stakeholders to translate requirements into scalable technical solutions. I also dedicate time to continuous learning because the cloud ecosystem evolves incredibly fast, and staying up to date is essential. What motivates and inspires you to be an active member of the Aviators/Microsoft community? The community is one of the best accelerators of professional growth. What motivates me most is the opportunity to learn from others while also giving back through sharing experiences, lessons learned, and practical solutions. I believe that technology is not just about tools—it's about people. The Microsoft community creates an environment where professionals can collaborate, innovate, and help each other succeed. Seeing someone solve a problem using knowledge I've shared is incredibly rewarding. Looking back, what advice do you wish you had been given earlier that you'd now share with those looking to get into STEM/technology? I would tell my younger self: Don't focus only on technology, focus on problem-solving and communication. Technical skills are important, but the ability to understand business challenges, communicate clearly, and work effectively with others often has an even greater impact on your career. I would also encourage people to: - Stay curious and never stop learning. - Build real projects rather than only collecting certifications. - Don't be afraid of failure—every mistake is an opportunity to learn. - Invest in your professional network early. The technology will change throughout your career, but adaptability and curiosity will always remain valuable. What has helped you grow professionally? Several factors have contributed to my growth: - Working on diverse and challenging projects. - Learning from experienced mentors and colleagues. - Being willing to step outside my comfort zone. - Participating in technical communities and events. - Maintaining a mindset of continuous improvement. Some of my biggest learning moments came from difficult projects where I had to solve problems I had never encountered before. Those experiences often teach more than success alone. If you had a magic wand that could create a feature in Logic Apps, what would it be and why? If I had a magic wand, I'd add an AI-powered end-to-end message tracking feature in Logic Apps that automatically follows a message across all workflows and Azure services it traverses. It would provide a single, intelligent view of the entire journey, making troubleshooting and root-cause analysis much faster and easier. News from our product group Your Certificate Renewed. Your Gateway Didn't Notice. Learn how certificate renewal can create outages when Azure Application Gateway does not detect an updated certificate in Azure Key Vault. The article explains certificate refresh behavior and practical steps for ensuring renewed certificates propagate reliably to dependent gateway infrastructure. How to Validate That Your BizTalk SB-Messaging Adapter Is Really Using AMQP Prepare BizTalk Server integrations for the retirement of the legacy Service Bus Messaging Protocol by confirming that the SB-Messaging adapter uses AMQP. This guide covers the required BizTalk Server 2020 hotfix and shows how to verify active AMQP-over-TLS connections on port 5671 across every relevant host and messaging configuration. Migrate Data Ingestion from Data Collector to Log Ingestion - Part 2 Continue migrating from the deprecated Data Collector API to the Azure Monitor Log Ingestion API by handling its smaller payload limit. The article demonstrates how to calculate and split large datasets into appropriately sized chunks in Azure Logic Apps so ingestion requests remain below the 1 MB limit. Bring Azure Logic Apps connectors into your .NET applications with the Azure Connectors SDK Explore the preview Azure Connectors SDK for calling Azure Logic Apps connectors directly from .NET applications without hosting a workflow. Strongly typed asynchronous clients, Azure Identity integration, and support for managed identities make it easier to connect application code to Microsoft and third-party services. Agentic Refactoring of Legacy Integration Workloads to Azure Logic Apps Standard See how agentic AI can accelerate the refactoring of legacy integration workloads into Azure Logic Apps Standard. This Microsoft Azure Developers video explores an AI-assisted modernization approach for analyzing existing solutions and moving them toward cloud-native workflows. Connect Azure Functions to SharePoint using Managed Connectors Learn how Azure Functions can connect to SharePoint using managed connectors. This Microsoft Azure Developers video demonstrates how connector capabilities simplify authentication and integration between function code and SharePoint. Connect SaaS & Enterprise Systems with Azure Functions This Microsoft Azure Developers video showcases how Azure Functions can use managed connectors for scalable, event-driven automation. It demonstrates integration with services such as SharePoint and Teams, highlighting how triggers and actions can reduce the need for manual polling and simplify authentication handling. The session walks through building practical workflows that connect SaaS and enterprise systems using Azure Functions. News from our community Logic Apps Community Day — 3 December 2026 Post by Ahmed Bayoumy Logic Apps Community Day returns on 3 December 2026 as a free, online event streamed live on YouTube. The program focuses on Logic Apps, the wider Azure integration stack, and AI patterns built on integration platforms. Organizers describe eight community speaking slots, combining longer sessions with lightning talks, and invite practitioners to submit examples, client cases, comparisons, or AI features. The event is intended for a worldwide audience and includes discussions, a published agenda, and opportunities for community members to share practical experience. Azure Logic Apps: Workflow Automation, Enterprise Integration, Connectors, B2B, Security, Networking, Monitoring, DevSecOps, Governance, and AI-Enable Post by Sanjeeve Kumar Gajadi This extensive guide presents Azure Logic Apps as an enterprise orchestration and integration layer rather than only a visual automation tool. It discusses Consumption and Standard hosting, triggers, actions, connectors, API Management, Service Bus, Event Grid, SAP, B2B protocols, managed identities, private networking, monitoring, reliability, DevOps, governance, and cost management. The article also considers AI-enabled orchestration and human approval patterns. Its central guidance is to design workflows around business processes, resilience, security, observability, and operational ownership while moving complex computation to suitable application services. Azure Logic Apps Handbook: 50 Expert Tips and Best Practices Post by Sandro Pereira Sandro Pereira introduces a free handbook containing 50 expert tips and best practices for Azure Logic Apps. The guide is aimed at architects, developers, integration specialists, DevOps engineers, and leaders working with cloud automation. Its coverage includes Logic Apps capabilities, practical use cases, workflow optimization, security, common pitfalls, and implementation strategies. The accompanying article explains that the handbook is intended to help readers design reliable, scalable, and maintainable workflows, and provides access to the downloadable resource through the linked publication. Build and Debug Logic Apps Standard Locally in VS Code Post by Stephen W. Thomas Stephen W. Thomas demonstrates how to build and debug Azure Logic Apps Standard workflows locally in Visual Studio Code without deploying resources to Azure. The walkthrough covers installing the extension, creating a stateful workflow with built-in operations, using local storage emulation, and sending a request from Postman. It also shows how to pause workflow execution at a breakpoint and inspect the results. The accompanying guide helps developers reproduce the setup and explore a practical local development loop while avoiding Azure charges during development and debugging. Azure API Management Premium v2 Workspaces and Dedicated Workspace Gateways in a Private Network Post by Şahin Özdemir Şahin Özdemir shares lessons from configuring Azure API Management Premium v2 workspaces and dedicated workspace gateways in a fully private network. The article covers Premium v2 virtual network integration, workspace isolation for multiple teams, internal-only workspace gateways, required Bicep resources and associations, and network security group rules. It also calls out deployment pitfalls and the less obvious Microsoft.ApiManagement/gateways/configConnections resource used to associate workspaces with gateways. The first part keeps API Management externally accessible while placing workspaces and their gateways inside the private network. Getting Started with Logic Apps Standard (in 2026) Video by Stephen W. Thomas Stephen W. Thomas shows how to set up Azure Logic Apps Standard locally in Visual Studio Code in under five minutes with no Azure charges. The updated installation brings in the Azure Functions runtime, Azure tooling, C# support, and storage emulators. The video creates a local workspace using built-in connectors, starts the workflow with F5, copies its callable URL, and sends a request from Postman. It also demonstrates breakpoints, debugger variables, action inputs, and stepping into custom in-process C# code for a complete local development experience.377Views0likes0CommentsBring Azure Logic Apps connectors into your .NET applications with the Azure Connectors SDK
Modern business applications rarely work in isolation. An order exception might need an email, a support case might need a Teams notification, and a completed document might need to be stored in SharePoint. Developers can build each integration directly against a service API, but that also means owning different authentication models, request and response shapes, pagination rules, and error handling for every service. The Azure Connectors SDK brings the typed experience of a .NET client library to Connector Namespace, which makes the Logic Apps and Power Platform connector runtime available to developers as a programmable integration layer. Your application can call connector operations through generated clients and models while Azure manages the connection to the external service. In this post, we will build a small Azure function app that reacts to a new email through a Connector trigger and sends a formatted review email through the Office 365 Outlook connector. The same pattern can then be extended to many other business systems. Preview: Azure Connectors SDK is currently in preview. Preview features are provided without a service-level agreement and are not recommended for production workloads. APIs and setup steps can change before general availability. Why this matters Integration code often starts with one HTTP call and grows into a collection of service-specific concerns. The Azure Connectors SDK gives .NET developers: Typed clients, request models, and response models generated from connector contracts Async operations with cancellation-token support Azure credential integration for authenticating the calling application Consistent connector exceptions and diagnostics Built-in retry support for transient failures Pagination, binary payload, and dynamic-schema support where connectors expose them OpenTelemetry integration for tracing connector calls Access to a broad connector ecosystem that includes Microsoft 365, Azure services, data platforms, storage, messaging, and SaaS applications The SDK does not put external-service credentials in your application. Instead, your code authenticates to a Connector Namespace connection. That connection holds the authorization for Office 365 Outlook or another target service. Scenario: notify operations about an order exception Imagine an order service that flags transactions for manual review by sending an email to an Office 365 mailbox. The subject identifies the order and the body briefly explains the exception: To: orders@contoso.com Subject: Order exception: SO-10482 Body: Customer requested a delivery-address change after payment. Connector Namespace polls the mailbox for new messages matching the subject filter and calls an Azure function app's Connector trigger. The function reads the typed email payload and sends a formatted review email to a separate operations inbox. Unlike an HTTP-triggered function, there is no application endpoint or 202 Accepted response to invoke. Prerequisites You need: An Azure subscription in which Connector Namespace is available Permission to create Connector Namespace resources and connections .NET 10 SDK Azure Functions Core Tools v4 Azure CLI Azure Developer CLI ( azd ) for deployment, or an existing .NET 10 isolated-worker function app An Office 365 account that can authorize the connection and send email At the time of writing, Connector Namespace is available in a limited set of preview regions. Confirm current region availability before creating the resource. 1. Create an Office 365 connection First sign in and select the subscription that will own the Connector Namespace: az login az account set --subscription "<subscription-id>" $subscriptionId = "<subscription-id>" $resourceGroup = "<resource-group>" $namespaceName = "<connector-namespace-name>" $connectionName = "office365-orders" $location = "<supported-azure-region>" $apiVersion = "2026-05-01-preview" $nsId = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup/providers/Microsoft.Web/connectorGateways/$namespaceName" Create a Connector Namespace with a system-assigned managed identity: $namespace = @{ location = $location identity = @{ type = "SystemAssigned" } properties = @{} } | ConvertTo-Json -Depth 5 -Compress $tempFile = Join-Path $env:TEMP "connector-namespace.json" [System.IO.File]::WriteAllText($tempFile, $namespace) az rest --method PUT ` --uri "https://management.azure.com${nsId}?api-version=$apiVersion" ` --body "@$tempFile" ` --headers "Content-Type=application/json" ` --output none Remove-Item $tempFile Create the Office 365 connection: $connection = @{ properties = @{ connectorName = "office365" } } | ConvertTo-Json -Depth 5 -Compress $tempFile = Join-Path $env:TEMP "connector-connection.json" [System.IO.File]::WriteAllText($tempFile, $connection) az rest --method PUT ` --uri "https://management.azure.com${nsId}/connections/${connectionName}?api-version=$apiVersion" ` --body "@$tempFile" ` --headers "Content-Type=application/json" ` --output none Remove-Item $tempFile The new connection is not authorized yet. Request an OAuth consent link and open it in your browser: $consentRequest = @{ parameters = @( @{ redirectUrl = "https://portal.azure.com" parameterName = "token" } ) } | ConvertTo-Json -Depth 5 -Compress $tempFile = Join-Path $env:TEMP "connector-consent.json" [System.IO.File]::WriteAllText($tempFile, $consentRequest) $consent = az rest --method POST ` --uri "https://management.azure.com${nsId}/connections/${connectionName}/listConsentLinks?api-version=$apiVersion" ` --body "@$tempFile" ` --headers "Content-Type=application/json" ` --output json | ConvertFrom-Json Remove-Item $tempFile Start-Process $consent.value[0].link Complete the sign-in and consent flow. Then verify that the connection reports Connected : az rest --method GET ` --uri "https://management.azure.com${nsId}/connections/${connectionName}?api-version=$apiVersion" ` --output json | ConvertFrom-Json | Select-Object -ExpandProperty properties | Select-Object -ExpandProperty statuses 2. Allow your local identity to call the connection OAuth consent authorizes the connection to call Office 365. A separate access policy authorizes your application to call the connection. This distinction is important: without the policy, the runtime call fails with HTTP 403 and a missing connection ACL message. Add an access policy for the identity currently signed in to Azure CLI: $userObjectId = az ad signed-in-user show --query id --output tsv $tenantId = az account show --query tenantId --output tsv $policy = @{ properties = @{ principal = @{ type = "ActiveDirectory" identity = @{ objectId = $userObjectId tenantId = $tenantId } } } } | ConvertTo-Json -Depth 6 -Compress $tempFile = Join-Path $env:TEMP "connector-policy.json" [System.IO.File]::WriteAllText($tempFile, $policy) az rest --method PUT ` --uri "https://management.azure.com${nsId}/connections/${connectionName}/accessPolicies/local-dev?api-version=$apiVersion" ` --body "@$tempFile" ` --headers "Content-Type=application/json" ` --output none Remove-Item $tempFile Access-policy changes can take a few minutes to reach the connector runtime. Finally, retrieve the connection runtime URL. Treat this value as application configuration rather than source code: $connection = az rest --method GET ` --uri "https://management.azure.com${nsId}/connections/${connectionName}?api-version=$apiVersion" ` --output json | ConvertFrom-Json $connectionRuntimeUrl = $connection.properties.connectionRuntimeUrl 3. Create the Azure function app Create an isolated-worker function app with the current Core Tools template. Some Core Tools v4 versions do not offer net10.0 as a func init --target-framework option; use the .NET 9 template, then change the generated project's TargetFramework to net10.0 before building: func init ConnectorsSdkOrderAlerts --worker-runtime dotnet-isolated --target-framework net9.0 Set-Location ConnectorsSdkOrderAlerts In ConnectorsSdkOrderAlerts.csproj , set: <TargetFramework>net10.0</TargetFramework> Add the connector packages: dotnet add package Azure.Connectors.Sdk --version 0.13.0-preview.1 dotnet add package Azure.Identity dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Connector --version 0.2.0-alpha Register an Azure credential and only the connector client this function needs. DefaultAzureCredential can use your Azure CLI identity locally and the function app's managed identity in Azure: using Azure.Connectors.Sdk; using Azure.Core; using Azure.Identity; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults() .ConfigureServices((hostContext, services) => { services.AddSingleton<TokenCredential>(new DefaultAzureCredential()); services.AddOffice365Client( hostContext.Configuration.GetSection("Connectors:Office365")); }) .Build(); host.Run(); Add the function. The Connector trigger binds the OnNewEmailV3 callback to a typed payload. Filter the subject again in code, HTML-encode untrusted email fields, and send the review message through the generated SendEmailInput model: using System.Text.Encodings.Web; using Azure.Connectors.Sdk.Office365; using Azure.Connectors.Sdk.Office365.Models; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Extensions.Connector; public sealed class OperationalAlertFunctions { private const string SubjectPrefix = "Order exception:"; private readonly Office365Client _office365Client; public OperationalAlertFunctions(Office365Client office365Client) { this._office365Client = office365Client; } [Function("OnOrderExceptionEmail")] public async Task OnOrderExceptionEmailAsync( [ConnectorTrigger] Office365OnNewEmailTriggerPayload payload, CancellationToken cancellationToken) { foreach (var message in payload.Body?.Value ?? []) { if (message?.Subject?.StartsWith( OperationalAlertFunctions.SubjectPrefix, StringComparison.OrdinalIgnoreCase) != true) { continue; } var orderId = message.Subject[OperationalAlertFunctions.SubjectPrefix.Length..].Trim(); if (string.IsNullOrWhiteSpace(orderId)) { continue; } var email = new SendEmailInput { To = "operations@contoso.com", Subject = $"Order {orderId} requires review", Body = "<h2>Order review required</h2>" + $"<p><strong>Order:</strong> {HtmlEncoder.Default.Encode(orderId)}</p>" + $"<p><strong>From:</strong> {HtmlEncoder.Default.Encode(message.From ?? string.Empty)}</p>" + $"<p><strong>Reason:</strong> {HtmlEncoder.Default.Encode(message.BodyPreview ?? string.Empty)}</p>" }; await this._office365Client.SendEmailAsync(email, cancellationToken); } } } Use a monitored mailbox or folder separate from the operations inbox. Keep the outgoing subject different from the trigger's subject filter so the notification cannot trigger itself. For production workloads, account for repeated callbacks and partial failures within a batch before performing non-idempotent actions such as sending mail. 4. Deploy and register the Connector trigger Keep the runtime URL out of source control. Set it for local development, then deploy the function app with a system-assigned managed identity and the same setting in its application configuration: $env:Connectors__Office365__ConnectionRuntimeUrl = $connectionRuntimeUrl The public Office 365 connector-trigger sample is a downloadable .NET 10 function app with deployment infrastructure, an OnNewEmail binding, and post-deploy trigger registration. Use its azd up workflow or deploy this function app through your existing pipeline. A locally running Functions host is not reachable by the Connector Namespace polling callback unless you provide a secure public callback endpoint. Once the function app is deployed, add its managed identity to the connection's access policies, just as you added your CLI identity for local development. For a system-assigned identity, get its principal ID and use it in the access policy from step 2 instead of $userObjectId : $functionAppName = "<function-app-name>" $functionObjectId = az functionapp identity show ` --resource-group $resourceGroup --name $functionAppName ` --query principalId --output tsv $policy = @{ properties = @{ principal = @{ type = "ActiveDirectory" identity = @{ objectId = $functionObjectId tenantId = $tenantId } } } } | ConvertTo-Json -Depth 6 -Compress $tempFile = [System.IO.Path]::GetTempFileName() try { [System.IO.File]::WriteAllText($tempFile, $policy) az rest --method PUT ` --uri "https://management.azure.com${nsId}/connections/${connectionName}/accessPolicies/order-alert-function?api-version=$apiVersion" ` --body "@$tempFile" ` --headers "Content-Type=application/json" ` --output none } finally { Remove-Item $tempFile } Obtain the Connector extension's system key and the function app's actual default hostname, then construct the callback URL for the deployed function. Do not assume that the hostname is <function-app-name>.azurewebsites.net ; the default hostname format can vary: $connectorExtensionKey = az functionapp keys list ` --resource-group $resourceGroup --name $functionAppName ` --query "systemKeys.connector_extension" --output tsv $functionAppHostname = az functionapp show ` --resource-group $resourceGroup --name $functionAppName ` --query "defaultHostName" --output tsv $callbackUrl = "https://$functionAppHostname/runtime/webhooks/connector?functionName=OnOrderExceptionEmail&code=$connectorExtensionKey" The system key is a secret. Do not log, publish, or commit the callback URL. Create the Office 365 polling trigger config using the same connection and a subject filter matching the incoming order messages: $triggerConfig = @{ properties = @{ operationName = "OnNewEmailV3" connectionDetails = @{ connectorName = "office365" connectionName = $connectionName } notificationDetails = @{ callbackUrl = $callbackUrl httpMethod = "Post" } parameters = @( @{ name = "folderPath"; value = "Inbox" } @{ name = "subjectFilter"; value = "Order exception:" } ) metadata = @{ destinationType = "functionApp" functionAppName = $functionAppName functionAppResourceGroup = $resourceGroup functionAppSubscriptionId = $subscriptionId functionName = "OnOrderExceptionEmail" recurrenceFrequency = "Minute" recurrenceInterval = "5" } } } | ConvertTo-Json -Depth 6 -Compress $tempFile = [System.IO.Path]::GetTempFileName() try { [System.IO.File]::WriteAllText($tempFile, $triggerConfig) az rest --method PUT ` --uri "https://management.azure.com${nsId}/triggerConfigs/order-exception-email?api-version=$apiVersion" ` --body "@$tempFile" ` --headers "Content-Type=application/json" ` --output none } finally { Remove-Item $tempFile } Confirm that the trigger config reports Enabled . Send a test email to the monitored mailbox, and allow for the polling interval before checking the function logs and the operations inbox: az rest --method GET ` --uri "https://management.azure.com${nsId}/triggerConfigs/order-exception-email?api-version=$apiVersion" ` --query "properties.{operation:operationName,state:state}" ` --output table Confirm all three outcomes before considering the test complete: The trigger config is Enabled and the function logs show the invocation. The operations inbox receives a review email with the expected order ID and reason. Unrelated messages do not produce review emails. From local development to Azure For a deployed function app, use its managed identity instead of a developer identity: Enable a system-assigned or user-assigned managed identity on the function app. Add that identity as an access policy on the Connector Namespace connection. Register DefaultAzureCredential or ManagedIdentityCredential as the TokenCredential . Store the connection runtime URL in function app configuration. Protect the Connector trigger callback with the Connector extension system key; use a stronger authorization model for production as appropriate. The external-service credential remains in the connector connection. The function app presents its Azure identity when it calls the runtime URL. The Connector Namespace uses the callback URL and its system key to invoke the function. Go beyond email The order-alert example is intentionally small, but the programming model supports much broader integration scenarios: Microsoft 365: work with Outlook, SharePoint, Teams, OneDrive, Excel, Planner, Forms, and Microsoft Entra ID-backed operations. Azure services: connect to Blob Storage, queues, tables, Event Grid, Event Hubs, Service Bus, Key Vault, Azure Monitor Logs, and Azure Data Factory. Business applications: integrate with Salesforce, Dynamics 365, Jira, ServiceNow-style workflows, DocuSign, Zendesk, and other SaaS systems represented in the connector catalog. Event-driven applications: register polling triggers that call back to an Azure function app when connector events occur. Data-rich APIs: consume paginated operations, binary content, and operations whose input or output schema is resolved dynamically. Observable integrations: capture connector activity in distributed traces with OpenTelemetry. Because connector clients are typed, developers can discover operations through IntelliSense and keep connector calls alongside the rest of their application code. The connection layer handles authorization to the external system, while Azure identity and access policies govern which application may use that connection. Troubleshooting The call returns 403 with “missing connection ACL.” The external OAuth connection may be healthy, but the calling Azure identity is not authorized. Add an access policy for the Azure CLI user during local development or the workload managed identity after deployment. Allow time for the policy to propagate. The connection remains in an error state. Complete the OAuth consent flow and query the connection again. Make sure the account used for consent has access to the target service. The client fails during startup because the runtime URL is missing. Make sure Connectors__Office365__ConnectionRuntimeUrl is present in the process environment. In a larger application, register only the connector clients whose configuration is available. Authentication works locally but fails in Azure. The local Azure CLI user and the function app managed identity are different principals. Add a separate connection access policy for the function app identity and use a managed-identity-capable credential in the deployed host. The email trigger does not fire. Verify the trigger config is Enabled , its operation is OnNewEmailV3 , its folderPath and subjectFilter match the test email, and its callback uses the deployed function's OnOrderExceptionEmail name and Connector extension system key. Polling is not instantaneous. Get started Explore the Azure Connectors SDK repository, try the samples, and tell us which connectors and application patterns would be most useful for your team. Azure Connectors SDK for .NET Azure Connectors SDK samples Downloadable Office 365 connector-trigger function app Azure Logic Apps connectors overview Azure Identity client library for .NET617Views0likes0CommentsMigrate Data Ingestion from Data Collector to Log Ingestion - Part 2
In Part1, we discussed how to use HTTP action to migrate from the deprecated Data Collector API to Log Ingestion API. However, since the deprecated Data Collector API was allowing message payload up to 30MB, some migration scenarios encountered issues; since the new Log Ingestion API has only 1MB payload limit. This applies to both HTTP action, and the preview (Log Ingestion connector) Azure Monitor service limits - Azure Monitor | Microsoft Learn When sending payload larger than 1MB, the HTTP action would fail with the error: In order to overcome this, we can chunk the array payload, before calling the Ingestion API. We need to chunk the array payload, so each produced chunk is around 800KB To do this, you can divide the size of your full payload, by the number of records it has, and this would give an average record size. Then divide 800,000 bytes with the average record size, and this will give you the chunk size. For example, if your payload size is 1,200,259 bytes, and the number of records is 2500, then the average record size is: 1,200,259 / 2,500 =~ 480 bytes To find the chunk size, we divide 800,000 bytes by 480 bytes 800,000 / 480 =~ 1666 records. So if we send around 1600 records, this should be less than 1MB. To chunk your array payload, we can use the chunk expression inside a compose action. You can use the expression below for chunking inside the compose action: After the compose action, add for-each action, and use the output of the compose action as an input: Inside the for-each, use the normal HTTP to send the logs, and in the body, choose the for-each current item332Views1like0Comments