Introduction to Azure Logic Apps
Azure Logic Apps is a cloud-based platform as a service (PaaS) that enables developers and organizations to automate workflows, integrate applications, data sources, and services across cloud and on-premises environments. Logic Apps provide a visual designer to build scalable integrations and automations with minimal code, while also supporting advanced expression-based logic and custom API calls.
At its core, a Logic App is a workflow definition expressed in JSON, executed by the Azure Logic Apps engine. Each workflow begins with a trigger—an event that starts the workflow—and continues with one or more actions that perform operations such as sending emails, calling REST APIs, transforming data, or executing conditional branches.
Why Logic Apps Matter
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →Logic Apps solve several critical challenges in modern enterprise integration:
- Rapid Integration: Connect to over 400 built-in connectors for services like Office 365, Salesforce, SAP, Service Bus, and more without writing boilerplate integration code.
- Serverless Architecture: No infrastructure to manage. Azure handles scaling, high availability, and execution automatically.
- Cost Efficiency: Pay only for what you use with a consumption-based pricing model. Ideal for variable workloads.
- Visual Development: The drag-and-drop designer allows both developers and non-developers to build workflows visually, reducing time to market.
- Hybrid Connectivity: With on-premises data gateways, Logic Apps can securely reach into your private network to integrate legacy systems.
- Enterprise Grade: Built-in support for Azure Active Directory authentication, role-based access control (RBAC), logging with Azure Monitor, and compliance certifications.
Core Concepts and Terminology
Before diving into setup, understanding these core concepts will help you navigate the Logic Apps ecosystem effectively:
- Workflow: The entire automation process, consisting of a trigger and actions.
- Trigger: The entry point that starts a workflow. Triggers can be polling-based (checking a schedule or queue) or push-based (reacting to an incoming webhook or event).
- Action: An individual step within a workflow, such as calling an API, executing a condition, or looping over data.
- Connector: A pre-built wrapper around a service API that handles authentication, paging, and error handling. Available in managed and built-in flavors.
- Run: A single execution instance of a workflow, triggered by an event or schedule.
- Integration Account: An optional companion resource for advanced B2B scenarios requiring XML validation, XSLT transforms, and trading partner agreements.
Logic App Types: Consumption vs. Standard
Azure offers two hosting models for Logic Apps, and choosing the right one is fundamental:
Consumption Logic Apps
Consumption Logic Apps run in a multi-tenant, serverless environment managed entirely by Azure. They scale out instantly and bill per execution and per action. This model is ideal for event-driven, low-to-medium volume integrations where cost optimization is paramount.
Standard Logic Apps
Standard Logic Apps run on a dedicated, single-tenant Azure Functions-based runtime, giving you more control over networking, scaling behavior, and compute isolation. They can be deployed in App Service Environments (ASE) with private networking. Standard Logic Apps bill based on the App Service Plan, making them suitable for high-volume, predictable workloads or scenarios requiring advanced networking security.
Step-by-Step: Creating Your First Logic App
Let's walk through creating a complete Logic App that monitors an email inbox for support requests, creates a ticket in a tracking system, and sends a confirmation. We'll use the Azure Portal, Azure CLI, and ARM template approaches to give you full flexibility.
Approach 1: Azure Portal Visual Designer
This is the quickest way to prototype and build workflows:
- Navigate to the Azure Portal and search for "Logic Apps" in the top search bar.
- Click Create and select Consumption as the resource type.
- Fill in the required fields: Resource Group, Logic App Name, Region, and optionally enable log analytics for monitoring.
- Click Review + Create, then Create to provision the resource.
- Once deployed, open the Logic App resource and select Logic App Designer from the left menu.
- Choose a trigger template. For this example, select When a new email arrives (Office 365 Outlook).
- Authenticate to Office 365 and configure the trigger: set the folder to "Inbox" and add a subject filter like "Support Request."
- Click New Step to add an action. Search for "Create a SharePoint item" and configure it to log each support email into a SharePoint list.
- Add another action: Send an email (Outlook) to send a confirmation reply to the sender.
- Save the workflow. Your Logic App is now live and will execute on every matching email.
Approach 2: Azure CLI
For automation and CI/CD pipelines, use the Azure CLI to create and manage Logic Apps programmatically:
#!/bin/bash
# Login to Azure
az login
# Set the target subscription
az account set --subscription "your-subscription-id"
# Create a resource group
az group create \
--name "rg-logicapps-demo" \
--location "westeurope"
# Create a Consumption Logic App
az logic workflow create \
--resource-group "rg-logicapps-demo" \
--name "SupportTicketWorkflow" \
--location "westeurope" \
--definition workflow-definition.json
# Enable diagnostics logging
az monitor diagnostic-settings create \
--resource "/subscriptions/sub-id/resourceGroups/rg-logicapps-demo/providers/Microsoft.Logic/workflows/SupportTicketWorkflow" \
--name "sendToLogAnalytics" \
--workspace "/subscriptions/sub-id/resourceGroups/rg-monitoring/providers/Microsoft.OperationalInsights/workspaces/central-logs" \
--logs '[{"category":"WorkflowRuntime","enabled":true}]'
# List recent runs
az logic workflow run list \
--resource-group "rg-logicapps-demo" \
--workflow-name "SupportTicketWorkflow" \
--max-items 10 \
-o table
Approach 3: ARM Template (Infrastructure as Code)
For production deployments, define your Logic App as an ARM template for repeatable, version-controlled infrastructure:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workflowName": {
"type": "string",
"defaultValue": "SupportTicketWorkflow"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
}
},
"resources": [
{
"type": "Microsoft.Logic/workflows",
"apiVersion": "2019-05-01",
"name": "[parameters('workflowName')]",
"location": "[parameters('location')]",
"properties": {
"state": "Enabled",
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"triggers": {
"When_a_new_email_arrives": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['office365']['connectionId']"
}
},
"method": "get",
"path": "/v2/OnNewEmail",
"queries": {
"folder": "Inbox",
"subjectFilter": "Support Request",
"importance": "Normal"
}
},
"recurrence": {
"frequency": "Minute",
"interval": 3
}
}
},
"actions": {
"Create_SharePoint_Item": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['sharepointonline']['connectionId']"
}
},
"method": "post",
"path": "/v1/datasets/@{encodeURIComponent(encodeURIComponent('https://contoso.sharepoint.com/sites/Support'))}/tables/@{encodeURIComponent(encodeURIComponent('SupportTickets'))}/items",
"body": {
"Title": "@triggerBody()?['subject']",
"Requester": "@triggerBody()?['from']",
"Description": "@triggerBody()?['body']"
}
}
},
"Send_confirmation_email": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['office365']['connectionId']"
}
},
"method": "post",
"path": "/v2/Mail",
"body": {
"to": "@triggerBody()?['from']",
"subject": "We received your support request",
"body": "Thank you for contacting support. Your ticket has been created."
}
},
"runAfter": {
"Create_SharePoint_Item": ["Succeeded"]
}
}
}
},
"parameters": {
"$connections": {
"value": {
"office365": {
"connectionId": "/subscriptions/sub-id/resourceGroups/rg-logicapps-demo/providers/Microsoft.Web/connections/office365",
"connectionName": "office365",
"id": "/subscriptions/sub-id/providers/Microsoft.Web/locations/westeurope/managedApis/office365"
},
"sharepointonline": {
"connectionId": "/subscriptions/sub-id/resourceGroups/rg-logicapps-demo/providers/Microsoft.Web/connections/sharepointonline",
"connectionName": "sharepointonline",
"id": "/subscriptions/sub-id/providers/Microsoft.Web/locations/westeurope/managedApis/sharepointonline"
}
}
}
}
}
}
]
}
Deploy this template using Azure CLI:
az deployment group create \
--resource-group "rg-logicapps-demo" \
--template-file logicapp-template.json \
--parameters workflowName=SupportTicketWorkflow
Working with Workflow Definition Language
Every Logic App workflow is defined using a JSON-based language. Understanding this format unlocks advanced capabilities and allows you to version-control your workflows in source repositories.
Trigger Configuration
Triggers define how your workflow starts. Here are common trigger patterns:
{
"triggers": {
"Recurrence_Schedule": {
"type": "Recurrence",
"recurrence": {
"frequency": "Day",
"interval": 1,
"schedule": {
"hours": ["09"],
"minutes": ["00"],
"timeZone": "Pacific Standard Time"
}
}
}
}
}
This trigger fires every weekday at 9:00 AM Pacific Time. The schedule property allows precise control over execution timing.
Conditional Logic and Switch Statements
Use conditions to branch workflow execution based on data values:
{
"actions": {
"Check_Priority": {
"type": "Switch",
"expression": "@triggerBody()?['priority']",
"cases": {
"High": {
"actions": {
"Escalate_to_Manager": {
"type": "ApiConnection",
"inputs": {
"host": { "connection": { "name": "@parameters('$connections')['office365']['connectionId']" } },
"method": "post",
"path": "/v2/Mail",
"body": {
"to": "manager@contoso.com",
"subject": "High Priority Escalation",
"body": "@triggerBody()?['description']"
}
}
}
}
},
"Low": {
"actions": {
"Log_to_Database": {
"type": "ApiConnection",
"inputs": {
"host": { "connection": { "name": "@parameters('$connections')['sql']['connectionId']" } },
"method": "post",
"path": "/v2/execute-stored-procedure",
"body": {
"procedureName": "sp_LogLowPriority",
"parameters": { "description": "@triggerBody()?['description']" }
}
}
}
}
}
},
"default": {
"actions": {
"Send_Notification": {
"type": "ApiConnection",
"inputs": {
"host": { "connection": { "name": "@parameters('$connections')['office365']['connectionId']" } },
"method": "post",
"path": "/v2/Mail",
"body": {
"to": "team@contoso.com",
"subject": "New Ticket - No Priority Set",
"body": "A ticket was created without a priority assignment."
}
}
}
}
}
}
}
}
Loops: For Each and Until
Process collections of items or implement retry logic with loops:
{
"actions": {
"Process_Order_Items": {
"type": "Foreach",
"foreach": "@triggerBody()?['lineItems']",
"actions": {
"Validate_Inventory": {
"type": "ApiConnection",
"inputs": {
"host": { "connection": { "name": "@parameters('$connections')['sql']['connectionId']" } },
"method": "post",
"path": "/v2/execute-stored-procedure",
"body": {
"procedureName": "sp_CheckInventory",
"parameters": {
"sku": "@item()?['sku']",
"quantity": "@item()?['quantity']"
}
}
}
}
},
"runAfter": { "Parse_Order": ["Succeeded"] }
},
"Wait_for_Approval": {
"type": "Until",
"expression": "@equals(variables('approvalStatus'), 'approved')",
"actions": {
"Check_Status": {
"type": "Http",
"inputs": {
"method": "GET",
"uri": "https://approval-system.contoso.com/api/status/@{variables('approvalId')}"
}
},
"Update_Status_Variable": {
"type": "SetVariable",
"inputs": {
"name": "approvalStatus",
"value": "@body('Check_Status')?['status']"
}
},
"Delay": {
"type": "Wait",
"inputs": {
"interval": {
"count": 30,
"unit": "Second"
}
}
}
},
"limit": {
"count": 60,
"timeout": "PT1H"
}
}
}
}
The Until loop polls an approval system every 30 seconds for up to 60 iterations or 1 hour, whichever comes first. This pattern is perfect for long-running human-in-the-loop processes.
Variables and Expressions
Logic Apps support variables for state management and a rich expression language for data manipulation:
{
"actions": {
"Initialize_Counters": {
"type": "InitializeVariable",
"inputs": {
"variables": [
{
"name": "processedCount",
"type": "Integer",
"value": 0
},
{
"name": "errorList",
"type": "Array",
"value": []
},
{
"name": "currentTimestamp",
"type": "String",
"value": "@{utcNow()}"
}
]
}
},
"Format_Date_For_Report": {
"type": "Compose",
"inputs": {
"formattedDate": "@{formatDateTime(triggerBody()?['eventDate'], 'yyyy-MM-dd')}",
"fiscalQuarter": "@{concat('Q', string(add(div(sub(int(lastIndexOf(string(triggerBody()?['eventDate']), '-'))), 3), 1)))}"
},
"runAfter": { "Initialize_Counters": ["Succeeded"] }
},
"Increment_Counter": {
"type": "IncrementVariable",
"inputs": {
"name": "processedCount",
"value": 1
},
"runAfter": { "Process_Item": ["Succeeded"] }
}
}
}
Common expression patterns include:
@coalesce(triggerBody()?['name'], 'Unknown')— provide fallback values@concat('Order-', triggerBody()?['id'])— string concatenation@if(greater(triggerBody()?['amount'], 1000), 'High Value', 'Standard')— inline conditionals@join(variables('errorList'), ', ')— array to string conversion@addDays(utcNow(), 7)— date arithmetic
Connectors and API Connections
Connectors are the bridge between your Logic App and external services. They fall into two categories:
Managed Connectors
Managed connectors are hosted and managed by Azure. They include services like Office 365, Salesforce, Dynamics 365, and Azure services. Authentication is handled through Azure AD or OAuth, and you create API connections once per account per region.
Built-in Connectors
Built-in connectors run directly within the Logic Apps runtime, offering lower latency and no external dependency. Examples include Azure Functions, Service Bus, Event Grid, and the HTTP connector for calling arbitrary REST endpoints.
Creating a Custom HTTP Connector Action
When no pre-built connector exists for your service, use the HTTP action to call any REST API:
{
"actions": {
"Call_External_Weather_API": {
"type": "Http",
"inputs": {
"method": "GET",
"uri": "https://api.weatherprovider.com/v3/forecast",
"headers": {
"Authorization": "Bearer @{variables('apiToken')}",
"Accept": "application/json"
},
"queries": {
"latitude": "@triggerBody()?['location']?['lat']",
"longitude": "@triggerBody()?['location']?['lng']",
"units": "metric"
},
"authentication": {
"type": "Raw",
"value": "@variables('apiToken')"
}
},
"retryPolicy": {
"type": "Exponential",
"interval": "PT10S",
"count": 3,
"minimumInterval": "PT5S",
"maximumInterval": "PT1M"
}
},
"Parse_Weather_Response": {
"type": "ParseJson",
"inputs": {
"content": "@body('Call_External_Weather_API')",
"schema": {
"type": "object",
"properties": {
"temperature": { "type": "number" },
"conditions": { "type": "string" },
"humidity": { "type": "number" }
}
}
},
"runAfter": { "Call_External_Weather_API": ["Succeeded"] }
}
}
}
The retryPolicy configuration implements exponential backoff, retrying up to 3 times with increasing delays. This is critical for resilient cloud integrations.
Error Handling and Scoped Execution
Production workflows must handle failures gracefully. Logic Apps provide scopes and error handling actions:
{
"actions": {
"Try_Block": {
"type": "Scope",
"actions": {
"Process_Payment": {
"type": "ApiConnection",
"inputs": {
"host": { "connection": { "name": "@parameters('$connections')['stripe']['connectionId']" } },
"method": "post",
"path": "/v1/charges",
"body": {
"amount": "@triggerBody()?['amount']",
"currency": "usd",
"source": "@triggerBody()?['token']"
}
}
},
"Update_Order_Status": {
"type": "ApiConnection",
"inputs": {
"host": { "connection": { "name": "@parameters('$connections')['sql']['connectionId']" } },
"method": "post",
"path": "/v2/execute-stored-procedure",
"body": {
"procedureName": "sp_UpdateOrderStatus",
"parameters": {
"orderId": "@triggerBody()?['orderId']",
"status": "paid"
}
}
},
"runAfter": { "Process_Payment": ["Succeeded"] }
}
},
"runAfter": {}
},
"Catch_Block": {
"type": "Scope",
"actions": {
"Log_Failure": {
"type": "ApiConnection",
"inputs": {
"host": { "connection": { "name": "@parameters('$connections')['azureloganalytics']['connectionId']" } },
"method": "post",
"path": "/v2/sendData",
"body": {
"eventType": "PaymentFailure",
"orderId": "@triggerBody()?['orderId']",
"error": "@result('Try_Block')?['error']",
"timestamp": "@{utcNow()}"
}
}
},
"Notify_Support": {
"type": "ApiConnection",
"inputs": {
"host": { "connection": { "name": "@parameters('$connections')['office365']['connectionId']" } },
"method": "post",
"path": "/v2/Mail",
"body": {
"to": "support@contoso.com",
"subject": "Payment Processing Failure",
"body": "Order @{triggerBody()?['orderId']} failed payment processing. Error: @{result('Try_Block')?['error']}"
}
},
"runAfter": { "Log_Failure": ["Succeeded"] }
},
"Set_Order_Status_Failed": {
"type": "ApiConnection",
"inputs": {
"host": { "connection": { "name": "@parameters('$connections')['sql']['connectionId']" } },
"method": "post",
"path": "/v2/execute-stored-procedure",
"body": {
"procedureName": "sp_UpdateOrderStatus",
"parameters": {
"orderId": "@triggerBody()?['orderId']",
"status": "payment_failed"
}
}
},
"runAfter": { "Notify_Support": ["Succeeded"] }
}
},
"runAfter": { "Try_Block": ["Failed", "TimedOut"] }
}
}
}
The runAfter property on Catch_Block specifies that it executes only when Try_Block fails or times out. This try-catch pattern ensures that failures are always handled and logged, preventing silent data loss.
On-Premises Connectivity with Data Gateway
Many enterprises need Logic Apps to reach systems behind firewalls. The on-premises data gateway enables secure, outbound-only connectivity to resources like SQL Server, file shares, SAP, and Oracle databases.
Setting Up the Gateway
- Download the on-premises data gateway installer from the Azure portal.
- Install it on a server within your network that has line-of-sight to the target systems. The server must run Windows and remain powered on continuously.
- During installation, sign in with your Azure account and register the gateway with a unique name.
- In the Azure Portal, navigate to your Logic App, open the Resource menu, and select Gateways. Create a connection resource referencing your gateway.
Connecting to On-Premises SQL Server
Once the gateway is registered, create an API connection and use it in your workflow:
{
"actions": {
"Query_OnPrem_Inventory": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['sql']['connectionId']"
}
},
"method": "get",
"path": "/v2/datasets/@{encodeURIComponent(encodeURIComponent('OnPremSQLServer'))}/tables/@{encodeURIComponent(encodeURIComponent('dbo.Inventory'))}/items",
"queries": {
"$filter": "Quantity lt 10",
"$top": 100
}
}
},
"Insert_Replenishment_Order": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['sql']['connectionId']"
}
},
"method": "post",
"path": "/v2/datasets/@{encodeURIComponent(encodeURIComponent('OnPremSQLServer'))}/tables/@{encodeURIComponent(encodeURIComponent('dbo.ReplenishmentOrders'))}/items",
"body": {
"ProductId": "@item()?['ProductId']",
"Quantity": 50,
"OrderDate": "@{utcNow()}"
}
},
"runAfter": { "Query_OnPrem_Inventory": ["Succeeded"] }
}
}
}
Monitoring, Logging, and Alerting
Observability is essential for production Logic Apps. Azure provides multiple layers of monitoring:
Azure Monitor and Log Analytics
Enable diagnostic settings to send workflow run data to Log Analytics for querying:
# Enable diagnostic settings via CLI
az monitor diagnostic-settings create \
--resource "/subscriptions/sub-id/resourceGroups/rg-logicapps-demo/providers/Microsoft.Logic/workflows/SupportTicketWorkflow" \
--name "workflowLogs" \
--workspace "/subscriptions/sub-id/resourceGroups/rg-monitoring/providers/Microsoft.OperationalInsights/workspaces/central-logs" \
--logs '[
{"category": "WorkflowRuntime", "enabled": true},
{"category": "WorkflowTrigger", "enabled": true}
]' \
--metrics '[
{"category": "AllMetrics", "enabled": true}
]'
Common Kusto queries for monitoring:
// Find all failed runs in the last 24 hours
AzureDiagnostics
| where ResourceType == "WORKFLOWS"
| where status == "Failed"
| where TimeGenerated > ago(24h)
| project TimeGenerated, resource_workflowName_s, status, error_code_s, error_message_s
| order by TimeGenerated desc
// Calculate success rate by workflow
AzureDiagnostics
| where ResourceType == "WORKFLOWS"
| summarize Total = count(),
Succeeded = countif(status == "Succeeded"),
Failed = countif(status == "Failed")
by resource_workflowName_s, bin(TimeGenerated, 1d)
| extend SuccessRate = round(Succeeded * 100.0 / Total, 2)
| project TimeGenerated, resource_workflowName_s, Total, Succeeded, Failed, SuccessRate
| order by TimeGenerated desc
// Identify the slowest actions across all workflows
AzureDiagnostics
| where ResourceType == "WORKFLOWS" and category == "WorkflowRuntime"
| extend durationSeconds = toreal(executionDurationMs) / 1000
| where durationSeconds > 30
| project TimeGenerated, resource_workflowName_s, actionName_s, durationSeconds
| order by durationSeconds desc
Setting Up Alerts
Create alerts for workflow failures to notify your operations team:
# Create an action group for email notification
az monitor action-group create \
--resource-group "rg-monitoring" \
--name "LogicAppFailureAlertGroup" \
--action email ops-team ops@contoso.com
# Create a metric alert for workflow failures
az monitor metrics alert create \
--resource-group "rg-monitoring" \
--name "WorkflowFailureAlert" \
--scopes "/subscriptions/sub-id/resourceGroups/rg-logicapps-demo/providers/Microsoft.Logic/workflows/SupportTicketWorkflow" \
--condition "total RunsFailed > 0" \
--window-size 5m \
--evaluation-frequency 1m \
--action "/subscriptions/sub-id/resourceGroups/rg-monitoring/providers/Microsoft.Insights/actionGroups/LogicAppFailureAlertGroup" \
--description "Alert when any workflow run fails"
Security and Access Control
Managed Identities
Instead of managing credentials, use Managed Identities to authenticate Logic Apps to Azure services:
# Enable system-assigned managed identity
az logic workflow identity assign \
--resource-group "rg-logicapps-demo" \
--name "SupportTicketWorkflow" \
--identity-type SystemAssigned
# Grant the identity access to Azure Key Vault secrets
az keyvault set-policy \
--name "contoso-keyvault" \
--object-id "$(az logic workflow show --resource-group rg-logicapps-demo --name SupportTicketWorkflow --query identity.principalId -o tsv)" \
--secret-permissions get list
In your workflow definition, reference Key Vault secrets securely:
{
"actions": {
"Get_Database_Password": {
"type": "Compose",
"inputs": {
"secret": "@{json(concat('{\"uri\":\"https://contoso-keyvault.vault.azure.net/secrets/database-password\"}'))}"
},
"managedIdentity": {
"type": "SystemAssigned"
}
}
}
}
RBAC and Least Privilege
Assign granular roles to control who can edit, trigger, or view Logic Apps:
- Logic App Contributor: Full management of Logic Apps but cannot modify access.
- Logic App Operator: Can enable/disable and run workflows but cannot modify definitions.
- Reader: View-only access to workflow definitions and run history.
# Grant developer team contributor access at resource group level
az role assignment create \
--assignee "dev-team-group-object-id" \
--role "Logic App Contributor" \
--resource-group "rg-logicapps-demo"
# Grant operations team operator access to a specific workflow
az role assignment create \
--assignee "ops-team-group-object-id" \
--role "Logic App Operator" \
--scope "/subscriptions/sub-id/resourceGroups/rg-logicapps-demo/providers/Microsoft.Logic/workflows/SupportTicketWorkflow"
Best Practices for Production Logic Apps
- Use Stateless Workflows When Possible: Avoid storing state across runs unless necessary. Each run should be self-contained and idempotent—processing the same input twice should produce the same result.
- Implement Retry Policies: Every external API call should have a retry policy configured. Use exponential backoff for transient failures and fixed delays for rate-limit recovery.
- Design for Idempotency: Use unique identifiers like
@triggerBody()?['id']to deduplicate operations. If a workflow retries, it should recognize previously completed work. - Keep Workflows Small and Focused: A single Logic App should perform one business function. Chain workflows together using HTTP triggers or messaging services like Service Bus for complex orchestrations.
- Use Variables Sparingly: Variables persist across actions within a run but consume memory. For large datasets, use the Compose action with
@outputs()references instead. - Parameterize Connections: Extract connection references into parameters so you can promote workflows across environments (dev, test, prod) without editing the definition.
- Enable Diagnostics Early: Configure Log Analytics from day one. Historical run data is invaluable for troubleshooting and capacity planning.
- Version Control Your Definitions: Export workflow definitions as JSON and store them in Git. Use Azure DevOps or GitHub Actions for CI/CD deployment.
- Test with Failure Injection: Simulate connector outages, invalid data, and timeouts in non-production environments to validate error handling paths.
- Set Concurrency Limits: For high-throughput triggers, configure
runtimeConfigurationto limit concurrent runs and prevent overwhelming downstream systems.
Concurrency Configuration Example
{
"triggers": {
"ServiceBus_Queue_Trigger": {
"type": "ApiConnection",
"inputs": {