🔀 Azure Integration

Azure Logic Apps
Complete Guide

From beginner to architecture level — triggers, actions, connectors, expressions, error handling, Service Bus, Storage, Function Apps, APIM, Event Grid, monitoring, CI/CD, and every enterprise integration pattern you need.

Beginner → Architecture24 Sections500+ ConnectorsLow-Code / Pro-CodeJSON Workflow Definitions

01What Is Azure Logic Apps?

Azure Logic Apps is a cloud-based integration platform (iPaaS) that lets you automate workflows, connect services, and orchestrate business processes — visually or via code. With 500+ built-in connectors, you can integrate Azure services, SaaS platforms (Salesforce, Office 365, Dynamics), on-premises systems, and custom APIs without writing infrastructure code.

🔌
500+ Connectors
Pre-built connectors for Azure, M365, Salesforce, SAP, Twitter, Twilio, and hundreds more
🎨
Visual Designer
Drag-and-drop workflow designer in Azure Portal — no code required for common scenarios
Event-Driven
React to events from queues, blobs, HTTP, timers, and external SaaS webhooks
🏗️
Enterprise Grade
B2B EDI processing, AS2/X12/EDIFACT, long-running workflows, stateful orchestration
🔄
Stateful & Stateless
Stateful workflows with full run history; stateless for high-throughput low-latency scenarios
🛡️
Managed Identity
Authenticate to Azure services without credentials using system or user-assigned identity

02Core Concepts & Terminology

Before building workflows, it helps to understand the foundational vocabulary that Logic Apps uses throughout its designer, JSON definitions, and documentation. These concepts map directly to how you structure, debug, and monitor your integrations in production. Mastering them early prevents confusion when reading run histories or troubleshooting connector failures. Think of each term as a building block — triggers start things, actions do things, connectors connect things, and run history shows you what happened.

TermDefinition
WorkflowA series of steps (trigger + actions) that execute in sequence or parallel
TriggerThe event that starts a workflow — HTTP request, timer, queue message, blob created, etc.
ActionA step in the workflow — call API, send email, write to DB, transform data, etc.
ConnectorA pre-built adapter for a specific service (Azure Storage, Outlook, SQL, Salesforce)
Run HistoryA log of every workflow execution — inputs, outputs, duration, status of each step
Managed ConnectorMicrosoft-hosted, auto-scaled connector infrastructure
Built-in ConnectorRuns in-process with the Logic App runtime — faster, VNet-aware, cheaper
Integration AccountContainer for B2B artifacts: schemas (XSD), maps (XSLT), certificates, partners
ISE (deprecated)Integration Service Environment — now replaced by Standard Logic Apps + VNet
DesignerVisual workflow editor in Azure Portal or VS Code

03Consumption vs Standard

Azure Logic Apps offers two hosting models that differ significantly in pricing, networking, performance, and deployment flexibility. Choosing the right plan upfront is critical because migrating between them later requires rebuilding workflows. Consumption is ideal for low-volume, simple integrations where you pay only for what you use, while Standard unlocks VNet isolation, multiple workflows per app, stateless execution, and full CI/CD support for enterprise production workloads. Evaluate your throughput, security, and DevOps requirements before committing to a plan.

FeatureConsumption (Multi-tenant)Standard (Single-tenant)
HostingShared multi-tenantDedicated single-tenant
Workflows per app1 workflowMultiple workflows
PricingPay per action executionFixed vCPU + memory/hr
Stateful workflows✓ Yes✓ Yes
Stateless workflows✗ No✓ Yes
VNet Integration✗ No✓ Yes
Private Endpoints✗ No✓ Yes
Built-in connectorsLimitedExpanded (Service Bus, Storage, HTTP native)
Custom code✗ No✅ inline C# scripts
Local developmentLimited✅ VS Code + Azurite emulator
CI/CD friendlyVia ARM/Bicep✅ Full file-based deployment
B2B / EDIIntegration AccountIntegration Account
SLA99.9%99.95%
DeploymentAzure Portal / ARMApp Service Plan / Zip deploy
Which to Choose?Use Consumption for simple, occasional workflows and quick integrations. Use Standard for production workloads needing VNet, multiple workflows, local dev, stateless high-throughput, or custom code.

04Triggers — All Types

Triggers are the entry point of every Logic App workflow — they define what event starts execution. Understanding trigger types is essential because they directly impact latency, cost, and reliability of your automation. Push-based triggers (webhooks, Event Grid) deliver near-instant response times, while polling triggers check for new data on an interval and incur costs per poll. Choose your trigger type based on how time-sensitive your workflow is and whether the source system supports push notifications.

Trigger Categories

CategoryExamplesHow It Works
HTTP / WebhookWhen HTTP request receivedLogic App exposes a URL; caller POSTs to it
Schedule / RecurrenceRecurrence trigger, Sliding WindowFires on a cron schedule or interval
PollingService Bus queue, Blob Storage, SQL, OutlookLogic Apps polls the source on an interval
Push / EventEvent Grid, Event Hub, Service Bus pushSource pushes events to Logic App webhook
ManualManual triggerOnly fires when you click 'Run' in Portal

HTTP Trigger (Webhook)

json
{
  "triggers": {
    "manual": {
      "type": "Request",
      "kind": "Http",
      "inputs": {
        "schema": {
          "type": "object",
          "properties": {
            "orderId": { "type": "string" },
            "amount":  { "type": "number" },
            "region":  { "type": "string" }
          },
          "required": ["orderId", "amount"]
        }
      }
    }
  }
}

Recurrence Trigger

json
{
  "triggers": {
    "Recurrence": {
      "type": "Recurrence",
      "recurrence": {
        "frequency": "Hour",
        "interval": 1,
        "startTime": "2025-01-01T00:00:00Z",
        "timeZone": "UTC",
        "schedule": {
          "hours": ["6", "12", "18"],
          "minutes": [0, 30]
        }
      }
    }
  }
}

Service Bus Trigger (Polling)

json
{
  "triggers": {
    "When_a_message_is_received_in_a_queue": {
      "type": "ApiConnection",
      "inputs": {
        "host": { "connection": { "name": "@parameters('$connections')['servicebus']['connectionId']" } },
        "method": "get",
        "path": "/@{encodeURIComponent('orders')}/messages/head/peek",
        "queries": { "maxMessageCount": 1 }
      },
      "recurrence": { "frequency": "Second", "interval": 30 }
    }
  }
}

Trigger Polling Interval Guide

Trigger TypeMin Poll IntervalNotes
Service Bus (Consumption)30 secondsBuilt-in (Standard) is push-based — much faster
Blob Storage1 minuteUse Event Grid trigger for near-real-time
SQL Server1 minutePolling adds load to DB — prefer change feed
Outlook / SharePoint1 minuteM365 connector rate limits apply
HTTP WebhookInstantSource calls Logic App directly — no polling
Event GridInstantPush-based — ideal for event-driven architectures

05Actions & Control Flow

Actions are the individual steps that execute after a trigger fires — they call APIs, transform data, send notifications, and control the flow of your workflow. Control flow actions like conditions, loops, and scopes let you build complex branching logic without writing code. In production, proper use of scopes and run-after configurations is what separates fragile workflows from resilient ones. Master these building blocks and you can orchestrate any business process, from simple notifications to multi-step approval chains with error recovery.

Control Flow Actions

ActionDescription
Condition (If/Else)Branch workflow based on a boolean expression
SwitchMulti-branch routing based on expression value
For EachLoop over array items — parallel by default (up to 20 concurrent)
UntilLoop until a condition becomes true (max iterations + timeout)
ScopeGroup actions into a named block for error handling
TerminateEnd the workflow run immediately with Succeeded / Failed / Cancelled
Delay / Delay UntilPause execution for a duration or until a specific time
Initialize VariableCreate a workflow-scoped variable
Set VariableUpdate an existing variable
Append to Array/StringAdd to a collection variable
Parse JSONParse a JSON string into a typed object for use in expressions
ComposeEvaluate and store an expression result without an API call
HTTPCall any REST API — GET, POST, PUT, DELETE, PATCH
ResponseReturn an HTTP response to the HTTP trigger caller

Condition Action

json
{
  "Condition": {
    "type": "If",
    "expression": {
      "and": [
        { "greater": ["@triggerBody()?['amount']", 1000] },
        { "equals": ["@triggerBody()?['region']", "EU"] }
      ]
    },
    "actions": {
      "Send_approval_email": { "..." : "..." }
    },
    "else": {
      "actions": {
        "Auto_approve": { "..." : "..." }
      }
    }
  }
}

For Each (Parallel Loop)

json
{
  "For_each_order": {
    "type": "Foreach",
    "foreach": "@body('Get_orders')?['value']",
    "runtimeConfiguration": {
      "concurrency": { "repetitions": 5 }
    },
    "actions": {
      "Process_order": { "..." : "..." }
    }
  }
}

HTTP Action — Call External API

json
{
  "Call_backend_API": {
    "type": "Http",
    "inputs": {
      "method": "POST",
      "uri": "https://api.mybackend.com/v1/orders",
      "headers": {
        "Content-Type": "application/json",
        "X-Correlation-Id": "@{triggerOutputs()?['headers']?['X-Request-Id']}"
      },
      "body": {
        "orderId": "@triggerBody()?['orderId']",
        "amount":  "@triggerBody()?['amount']",
        "processedAt": "@utcNow()"
      },
      "authentication": {
        "type": "ManagedServiceIdentity",
        "audience": "api://my-backend-api"
      }
    },
    "runAfter": {}
  }
}

06Connectors — Built-in & Managed

Built-in Connectors (Standard)

Run in-process with Logic App runtime. Faster, cheaper, VNet-aware, no separate connection resource.

  • HTTP / HTTP + Swagger
  • Azure Service Bus (built-in)
  • Azure Blob Storage (built-in)
  • Azure Event Hubs (built-in)
  • SQL Server (built-in)
  • Schedule / Recurrence
  • Request / Response
  • Inline Code (C# / JS)
  • Liquid / XSLT transforms
  • Flat File encode/decode
Managed Connectors

Microsoft-hosted, auto-scaled. Separate connection resource in Azure. 500+ available.

  • Office 365 / Outlook
  • SharePoint Online
  • Salesforce / Dynamics 365
  • SAP (on-premises gateway)
  • Twilio / SendGrid
  • Dropbox / OneDrive / Box
  • GitHub / Azure DevOps
  • Twitter / LinkedIn
  • ServiceNow / Zendesk
  • Stripe / PayPal

On-Premises Gateway Connectors

For on-premises data sources, install the On-Premises Data Gateway on a local machine. Supported: SQL Server, Oracle, MySQL, PostgreSQL, SAP, SharePoint on-premises, BizTalk, file system.

07Expressions & Functions

Expressions are the formula language of Logic Apps — they let you access trigger data, transform strings, perform calculations, and make decisions without writing custom code. Every dynamic value you see in the designer (green tokens) is an expression under the hood. In production workflows, mastering null-safe property access and coalesce patterns prevents runtime failures when upstream data is incomplete. Use expressions liberally in Compose actions to build intermediate payloads, making your workflows easier to debug and maintain.

Expression Syntax

text
@{expression}   — String interpolation inside a string
@expression     — Dynamic value (top-level field value)
@{...}@{...}    — Multiple expressions in one string

Commonly Used Functions

CategoryFunctionExample
Trigger/Action datatriggerBody()@triggerBody()?['orderId']
Trigger/Action databody('Action_Name')@body('Get_order')?['status']
Trigger/Action dataoutputs('Action_Name')@outputs('HTTP_call')['statusCode']
Stringconcat()@concat('Order-', triggerBody()?['id'])
StringtoUpper() / toLower()@toUpper(triggerBody()?['region'])
Stringsubstring()@substring(variables('str'), 0, 10)
Stringreplace()@replace(variables('text'), 'old', 'new')
Stringsplit()@split(triggerBody()?['tags'], ',')
Date/TimeutcNow()@utcNow('yyyy-MM-ddTHH:mm:ssZ')
Date/TimeaddHours() / addDays()@addHours(utcNow(), 24)
Date/TimeformatDateTime()@formatDateTime(utcNow(), 'dd/MM/yyyy')
Arraylength()@length(body('List_items')?['value'])
Arrayfirst() / last()@first(body('List_items')?['value'])
Arrayunion() / intersection()@union(variables('arr1'), variables('arr2'))
JSONjson()@json(body('HTTP_call'))
JSONstring()@string(variables('myObject'))
Mathadd() / sub() / mul() / div()@add(triggerBody()?['price'], 10)
Logicif()@if(equals(variables('x'),1),'yes','no')
Logicequals() / greater() / less()@equals(triggerBody()?['type'], 'premium')
Encodingbase64() / base64ToString()@base64(variables('secret'))
GUIDguid()@guid()

Null-Safe Property Access

text
// Use ?. to safely access nested properties (returns null instead of error)
@triggerBody()?['order']?['customer']?['email']

// Provide default with coalesce
@coalesce(triggerBody()?['region'], 'US')

// Check if property exists
@contains(triggerBody(), 'optionalField')

08Error Handling & Retry

Robust error handling separates production-grade workflows from fragile prototypes. Logic Apps provides run-after configuration, scope-based try/catch patterns, and configurable retry policies to handle transient failures gracefully. Without proper error handling, a single failed HTTP call can leave messages unprocessed, data inconsistent, or customers unnotified. Always wrap risky actions in scopes, configure exponential retry for external API calls, and use run-after to route failures to logging or dead-letter handling paths.

Run After Configuration

Every action has a runAfter property controlling when it executes based on the previous action's status.

json
{
  "Handle_error": {
    "type": "...",
    "runAfter": {
      "Process_order": ["Failed", "TimedOut", "Skipped"]
    }
  },
  "Continue_on_success": {
    "runAfter": {
      "Process_order": ["Succeeded"]
    }
  }
}

Scope + Run After (Try/Catch Pattern)

json
{
  "Try_scope": {
    "type": "Scope",
    "actions": {
      "Risky_action": { "..." : "..." }
    }
  },
  "Catch_scope": {
    "type": "Scope",
    "runAfter": {
      "Try_scope": ["Failed", "TimedOut"]
    },
    "actions": {
      "Log_error": {
        "type": "Http",
        "inputs": {
          "method": "POST",
          "uri": "https://mylogging.endpoint.com/error",
          "body": {
            "workflowId": "@{workflow()['run']['name']}",
            "errorMessage": "@{result('Try_scope')?[0]?['error']?['message']}",
            "timestamp": "@utcNow()"
          }
        }
      }
    }
  }
}

Retry Policy

json
{
  "Call_API": {
    "type": "Http",
    "inputs": { "..." : "..." },
    "retryPolicy": {
      "type": "exponential",
      "count": 5,
      "interval": "PT5S",
      "minimumInterval": "PT5S",
      "maximumInterval": "PT30M"
    }
  }
}
Retry Policy TypeDescription
NoneNo retries — action fails immediately on error
FixedFixed interval between retries (e.g. every 30s)
ExponentialIncreasing intervals with jitter — recommended for HTTP calls
Default4 retries at 7.5s, 12.5s, 19.5s, 26s intervals

09Variables & Data Operations

Variables in Logic Apps let you store and accumulate data across workflow steps — counters, arrays, intermediate results, and computed payloads. Unlike expressions which are evaluated inline, variables persist throughout the workflow run and can be updated inside loops. In production, use variables sparingly inside For Each loops (they serialize execution), and prefer Compose actions for intermediate calculations. Parse JSON is essential for turning untyped API responses into strongly-typed objects that the designer can auto-complete.

json
// Initialize variable
{
  "Init_counter": {
    "type": "InitializeVariable",
    "inputs": {
      "variables": [{
        "name": "counter",
        "type": "integer",
        "value": 0
      }]
    }
  }
}

// Increment variable
{
  "Increment_counter": {
    "type": "IncrementVariable",
    "inputs": {
      "name": "counter",
      "value": 1
    }
  }
}

// Append to array variable
{
  "Collect_results": {
    "type": "AppendToArrayVariable",
    "inputs": {
      "name": "resultList",
      "value": "@body('Process_item')"
    }
  }
}

// Compose — evaluate expression and store
{
  "Build_payload": {
    "type": "Compose",
    "inputs": {
      "orderId": "@triggerBody()?['id']",
      "total":   "@mul(triggerBody()?['qty'], triggerBody()?['price'])",
      "ts":      "@utcNow()"
    }
  }
}

Parse JSON — Create Typed Schema

json
{
  "Parse_order": {
    "type": "ParseJson",
    "inputs": {
      "content": "@body('HTTP_get_order')",
      "schema": {
        "type": "object",
        "properties": {
          "orderId": { "type": "string" },
          "amount":  { "type": "number" },
          "items":   { "type": "array" }
        }
      }
    }
  }
}

10Security & Authentication

Security in Logic Apps spans both inbound protection (who can trigger your workflow) and outbound authentication (how your workflow proves its identity to downstream services). Managed Identity is the gold standard — it eliminates stored credentials entirely and uses Azure RBAC for access control. In production, never expose Logic App trigger URLs directly, always rotate API keys stored in Key Vault, and use APIM or IP restrictions to lock down HTTP triggers. Every authentication method has trade-offs between security, complexity, and compatibility with legacy systems.

Authentication TypeUse CaseHow
Managed IdentityAzure services (Storage, Service Bus, SQL)Zero-credential, RBAC role assignment
OAuth 2.0Entra ID-protected APIsToken from Entra ID
API KeyThird-party APIs (SendGrid, Twilio)Key in header or query string
Basic AuthLegacy systemsUsername/password in Authorization header
Client CertificateHigh-assurance partner APIsTLS mutual auth
SAS TokenAzure Storage, Service Bus (legacy)Time-limited signature

Managed Identity on HTTP Action

json
{
  "Call_secure_api": {
    "type": "Http",
    "inputs": {
      "method": "GET",
      "uri": "https://myapi.azurewebsites.net/orders",
      "authentication": {
        "type": "ManagedServiceIdentity",
        "audience": "api://my-backend-app-id"
      }
    }
  }
}

Secure HTTP Trigger with SAS

Logic App HTTP triggers generate a URL with a built-in SAS signature. Store the URL in Key Vault. You can also add IP filtering and require Entra ID tokens via APIM in front of the Logic App.

⚠️
Never Expose Trigger URL DirectlyAlways put an APIM policy or Function App proxy in front of Logic App HTTP triggers in production. The trigger URL contains a SAS token that, if leaked, grants full workflow invocation access.

11Network Security & VNet

Network isolation is a hard requirement for enterprise workloads that process sensitive data or must comply with regulations like PCI-DSS or HIPAA. Standard Logic Apps support full VNet integration for outbound traffic and private endpoints for inbound access, ensuring your workflows never traverse the public internet. Use VNet integration when your Logic App needs to reach private databases, internal APIs, or on-premises systems through ExpressRoute or VPN gateways. For Consumption plans, the On-Premises Data Gateway provides a bridge to private networks, though with more operational overhead.

FeatureConsumptionStandard
VNet Integration (outbound)✗ No✓ Yes
Private Endpoints (inbound)✗ No✓ Yes
IP Restriction on trigger✓ Yes✓ Yes
On-Premises Gateway✓ Yes✓ Yes
Managed connector VNet✗ No✓ Yes
Built-in connector VNet-aware✗ No✓ Yes

VNet Integration (Standard)

bash
# Create Standard Logic App with VNet integration
az logicapp create \
  --name myLogicApp \
  --resource-group myRG \
  --plan myAppServicePlan \
  --storage-account mystorageaccount

# Integrate with VNet subnet
az webapp vnet-integration add \
  --name myLogicApp \
  --resource-group myRG \
  --vnet myVNet \
  --subnet mySubnet

12Service Bus Integration

Azure Service Bus is one of the most common integration partners for Logic Apps, enabling reliable asynchronous messaging between distributed systems. Logic Apps can trigger on queue or topic messages, process them, and explicitly complete or dead-letter based on outcome — implementing the competing consumer pattern without custom code. In production, always use peek-lock mode (not receive-and-delete) so messages return to the queue if your workflow fails mid-processing. For Standard Logic Apps, prefer the built-in Service Bus connector which is push-based, VNet-aware, and significantly faster than the managed polling connector.

Action / TriggerDirectionDescription
When a message is received in a queueTriggerPoll queue; fire when message available
When a message is received in a subscriptionTriggerPoll topic subscription
Send message to queueActionPublish message to a queue
Send message to topicActionPublish to a topic (fan-out)
Complete the message in a queueActionAcknowledge successful processing
Abandon the message in a queueActionReturn to queue for retry
Dead-letter the message in a queueActionMove to DLQ explicitly
Get messages from dead-letter queueActionDrain and inspect DLQ
Renew lock on messageActionExtend lock for long-running workflows

Full Pattern: Service Bus → Process → Complete/DLQ

json
{
  "triggers": {
    "When_message_arrives": {
      "type": "ApiConnection",
      "inputs": {
        "host": { "connection": { "name": "@parameters('$connections')['servicebus']['connectionId']" } },
        "method": "get",
        "path": "/@{encodeURIComponent('orders')}/messages/head/peek"
      },
      "recurrence": { "frequency": "Second", "interval": 30 }
    }
  },
  "actions": {
    "Parse_message": {
      "type": "ParseJson",
      "inputs": {
        "content": "@base64ToString(triggerBody()?['ContentData'])",
        "schema": { "..." : "..." }
      }
    },
    "Process_order": {
      "type": "Http",
      "inputs": { "method": "POST", "uri": "https://api.mybackend.com/orders", "body": "@body('Parse_message')" },
      "runAfter": { "Parse_message": ["Succeeded"] }
    },
    "Complete_message": {
      "type": "ApiConnection",
      "inputs": {
        "host": { "connection": { "name": "@parameters('$connections')['servicebus']['connectionId']" } },
        "method": "delete",
        "path": "/@{encodeURIComponent('orders')}/messages/complete",
        "queries": { "lockToken": "@triggerBody()?['LockToken']" }
      },
      "runAfter": { "Process_order": ["Succeeded"] }
    },
    "Deadletter_on_failure": {
      "type": "ApiConnection",
      "inputs": {
        "host": { "connection": { "name": "@parameters('$connections')['servicebus']['connectionId']" } },
        "method": "post",
        "path": "/@{encodeURIComponent('orders')}/messages/deadletter",
        "queries": {
          "lockToken": "@triggerBody()?['LockToken']",
          "deadLetterReason": "ProcessingFailed",
          "deadLetterErrorDescription": "@{body('Process_order')}"
        }
      },
      "runAfter": { "Process_order": ["Failed", "TimedOut"] }
    }
  }
}

13Storage Integration

Azure Storage is deeply integrated with Logic Apps, covering Blob Storage for file processing, Queue Storage for lightweight messaging, and Table Storage for simple key-value data. Common patterns include triggering workflows when files land in blob containers, processing CSV/JSON uploads, and archiving workflow outputs. In production, be aware that the blob trigger uses polling with a minimum 1-minute delay — for near-real-time file processing, pair Event Grid with an HTTP trigger instead. Use Managed Identity authentication to avoid storing connection strings in your workflow configuration.

Action / TriggerDescription
When a blob is added or modified (V2)Trigger on blob change — polling
Create blob (V2)Upload content as a new blob
Get blob content (V2)Download blob body into workflow variable
Get blob metadataRead blob properties, tags, content type
List blobs (V2)Enumerate container contents with prefix filter
Delete blob (V2)Remove a blob
Copy blobServer-side copy between containers or accounts
Extract archive to folderDecompress zip archive blob
Put a message on a queueEnqueue message to Storage Queue
Get messages from a queueDequeue messages from Storage Queue
Insert entity (Table)Add a new row to Azure Table Storage
Get entity (Table)Retrieve a row by PartitionKey + RowKey
Query entities (Table)OData filter query across table rows
💡
Event Grid + Blob for Real-TimeStorage Queue and Blob triggers use polling (1-minute minimum delay). For near-instant response to blob events, use Event Grid → Logic App HTTP trigger instead.

14Function Apps Integration

Logic Apps can call Azure Functions as actions — offloading complex code logic, transformations, or computations that would be awkward in expressions.

json
{
  "Call_function": {
    "type": "Function",
    "inputs": {
      "function": {
        "id": "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Web/sites/<funcApp>/functions/<funcName>"
      },
      "method": "POST",
      "headers": { "Content-Type": "application/json" },
      "body": {
        "orderId": "@triggerBody()?['orderId']",
        "items":   "@body('Parse_order')?['items']"
      }
    }
  }
}
Best PracticeUse Managed Identity to authenticate Logic App → Function App. Enable Entra ID authentication on the Function App and assign the Logic App's identity the required role. Avoids function keys entirely.

15APIM Integration

Two integration directions: APIM can call Logic Apps as a backend, and Logic Apps can call APIM-managed APIs as actions.

APIM → Logic App (Expose LA as REST API)

  1. 1
    Import Logic App into APIM
    APIM → APIs → Add API → Logic App. Auto-discovers the HTTP trigger schema.
  2. 2
    Set backend authentication
    APIM uses Managed Identity to call the Logic App trigger URL — no SAS in URL.
  3. 3
    Add inbound policies
    Rate limit, JWT validation, CORS — all applied before Logic App receives the call.
  4. 4
    Hide Logic App URL
    Clients only see the APIM gateway URL — Logic App URL stays internal.

Logic App → APIM-managed API

json
{
  "Call_orders_api_via_APIM": {
    "type": "Http",
    "inputs": {
      "method": "POST",
      "uri": "https://myAPIM.azure-api.net/orders",
      "headers": {
        "Ocp-Apim-Subscription-Key": "@parameters('apimSubscriptionKey')",
        "Content-Type": "application/json"
      },
      "body": "@triggerBody()"
    }
  }
}

16Event Grid Integration

Event Grid delivers events to Logic Apps via a push webhook — no polling, near-instant delivery. Subscribe to events from Storage, Service Bus, Resource Manager, custom topics, and 60+ Azure services.

json
// Logic App trigger for Event Grid events
{
  "triggers": {
    "When_Event_Grid_event_occurs": {
      "type": "ApiConnectionWebhook",
      "inputs": {
        "host": { "connection": { "name": "@parameters('$connections')['azureeventgrid']['connectionId']" } },
        "path": "/subscriptions/@{encodeURIComponent('<sub-id>')}/providers/@{encodeURIComponent('Microsoft.Storage.StorageAccounts')}/resource/eventSubscriptions",
        "body": {
          "properties": {
            "destination": { "endpointType": "webhook", "properties": { "endpointUrl": "@{listCallbackUrl()}" } },
            "filter": { "includedEventTypes": ["Microsoft.Storage.BlobCreated"] }
          }
        }
      }
    }
  }
}

17SQL & Cosmos DB Integration

Database integration is central to most enterprise workflows — whether you are reading order data, writing audit logs, or syncing records between systems. Logic Apps provides native connectors for both Azure SQL and Cosmos DB with triggers that detect new or modified data automatically. For SQL, prefer stored procedures over inline queries for complex operations to keep your workflow definitions clean and maintainable. For Cosmos DB, the change feed trigger is particularly powerful — it fires on every document create or update, enabling real-time event-driven architectures without polling overhead.

SQL Server Actions

ActionDescription
Execute a SQL queryRun any SELECT/INSERT/UPDATE/DELETE statement
Get rowsReturn rows from a table with OData filter
Insert rowAdd a new row to a table
Update rowModify an existing row by primary key
Delete rowRemove a row by primary key
Execute stored procedureCall a stored procedure with parameters
When an item is created (trigger)Poll for new rows inserted since last run
When an item is modified (trigger)Poll for updated rows

Cosmos DB Actions

ActionDescription
Create or update documentUpsert a JSON document by ID
Get documentRetrieve a document by ID and partition key
Query documentsExecute a SQL API query
Delete documentRemove a document by ID
When a document is created or modified (trigger)Change feed trigger — new/modified docs

18Other Azure Services

Beyond the core integration services, Logic Apps connects to the broader Microsoft ecosystem including Office 365, Teams, SharePoint, Key Vault, Azure Monitor, and AI services. These connectors turn Logic Apps into a universal automation hub — processing emails, posting notifications, managing secrets, and even calling AI models as workflow steps. In production, combine multiple connectors to build end-to-end business processes: for example, an email attachment triggers document AI extraction, results go to SQL, and a Teams notification confirms completion. Always use Key Vault references for secrets rather than hardcoding values in parameters.

📧
Office 365 / Outlook
Send/receive emails, create calendar events, read attachments — most popular connector.
📋
SharePoint Online
Create/update list items, upload files to document libraries, trigger on item changes.
🔔
Teams
Post adaptive cards to channels, create meetings, send DMs, react to Teams events.
📊
Azure Monitor
Create alerts, query Log Analytics (KQL), emit custom metrics from workflow.
🔑
Key Vault
Get secrets securely inside workflows — no hardcoded credentials anywhere.
🤖
Azure AI / Cognitive
Call Document Intelligence, Language, Vision, OpenAI from workflow steps.

19Monitoring & Diagnostics

Monitoring is non-negotiable for production Logic Apps — you need visibility into run success rates, latency, and failure root causes. Azure provides built-in run history with full input/output capture for every action, plus integration with Azure Monitor metrics and Log Analytics for alerting and KQL-based querying. Set up alerts on failed runs immediately after deployment — silent failures are the most dangerous kind. For high-volume workflows, enable diagnostic settings to stream logs to Log Analytics where you can build dashboards and correlate failures across multiple workflows.

Run History

Every workflow run is stored with full inputs, outputs, duration, and status of every action. Available in Azure Portal → Logic App → Run History. Retention: 90 days (Consumption), configurable (Standard).

MetricDescriptionAlert Condition
Runs StartedTotal workflow executionsSpike or drop detection
Runs SucceededSuccessful completionsLow vs Runs Started = failures
Runs FailedFailed executions> 0 — always alert
Run LatencyAverage workflow duration> expected threshold
Actions Started / Succeeded / FailedPer-action granularityFailed > 0
Billing ExecutionsBillable action countCost monitoring

KQL — Failed Runs in Last Hour

kql
AzureDiagnostics
| where ResourceType == "WORKFLOWS/RUNS"
| where status_s == "Failed"
| where TimeGenerated > ago(1h)
| project TimeGenerated, resource_workflowName_s,
          startTime_t, endTime_t, error_code_s, error_message_s
| order by TimeGenerated desc

20CI/CD & DevOps

Treating Logic Apps as code is essential for team collaboration, environment promotion, and rollback safety. Standard Logic Apps use a file-based structure that fits naturally into Git repositories and CI/CD pipelines, while Consumption Logic Apps rely on ARM/Bicep templates for infrastructure-as-code deployment. Always parameterize environment-specific values (connection strings, URLs, keys) so the same workflow definition deploys cleanly across dev, staging, and production. Use GitHub Actions or Azure DevOps pipelines to automate deployment on every merge to main, with approval gates for production.

Standard Logic App — File Structure

text
myLogicApp/
├── host.json                    ← Runtime configuration
├── local.settings.json          ← Local dev settings
├── connections.json             ← Connector connections
├── parameters.json              ← Parameter values per environment
└── Workflows/
    ├── OrderProcessing/
    │   └── workflow.json        ← Workflow definition
    └── DLQHandler/
        └── workflow.json

GitHub Actions — Deploy Standard Logic App

yaml
name: Deploy Logic App
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Login to Azure
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    - name: Deploy Logic App workflows
      uses: Azure/logicapps-deploy@v2
      with:
        la-name: myLogicApp
        resource-group: myRG
        artifacts-location: ./myLogicApp

Consumption — Export & Deploy via ARM

bash
# Export existing Logic App as ARM template
az logic workflow export \
  --resource-group myRG \
  --name myLogicApp \
  --sku Free > workflow-arm.json

# Deploy ARM template
az deployment group create \
  --resource-group myRG \
  --template-file workflow-arm.json \
  --parameters @parameters.prod.json

21Architecture Patterns

Logic Apps shines brightest when used as the orchestration layer in well-known enterprise integration patterns. These patterns solve recurring problems — event fan-out, document pipelines, human-in-the-loop approvals, B2B message exchange, and scheduled data synchronization. In production, combine multiple patterns: an event-driven trigger feeds into a document processing pipeline that ends with a notification. Start with a proven pattern rather than inventing custom architectures, and you will get to production faster with fewer edge cases to handle.

🎯
Event-Driven Orchestration
Event Grid event → Logic App → fan-out to Service Bus, email, DB, Teams notification.
📄
Document Processing Pipeline
Blob upload → trigger → AI Document Intelligence → parse → insert to SQL → notify via Teams.
🔄
Approval Workflow
HTTP/email trigger → send approval email → wait for response → branch on Approve/Reject.
🏭
B2B EDI Integration
AS2/X12/EDIFACT partner messages → decode → transform (XSLT) → route to ERP system.
Scheduled Data Sync
Recurrence → query source DB → transform → upsert to destination → send summary report.
🔔
Alert & Notification Hub
Monitor multiple sources → normalize alerts → route to Teams/email/PagerDuty based on severity.

22Logic Apps vs Functions vs APIM

One of the most common architecture questions is when to use Logic Apps versus Azure Functions versus API Management — and the answer is usually "all three together." Each service excels at a different layer: APIM handles API security and traffic management, Logic Apps orchestrates multi-step workflows and SaaS integrations, and Functions executes custom business logic and computations. Understanding their strengths prevents you from forcing one tool to do another's job. Use this comparison to assign the right responsibility to the right service in your architecture.

DimensionLogic AppsAzure FunctionsAPIM
Primary purposeWorkflow orchestration & integrationEvent-driven compute & code executionAPI gateway & management
Programming modelVisual / declarative JSONCode (C#, JS, Python, Java, PS)XML policy + config
Connectors500+ managed connectorsBindings (fewer, code-driven)Via send-request policy
State managementBuilt-in stateful runsDurable Functions onlyStateless per request
Long-runningDays/weeks (stateful)Only with Durable FunctionsNo (sync only)
Best forSaaS integrations, approvals, ETLCustom logic, APIs, event processingAPI security, routing, rate limiting
Cold startMinimalCan occur (Consumption plan)None (always warm)
Local devVS Code (Standard)Full local emulationLimited
Pricing unitPer action / per vCPUPer execution + GB-sPer call / per unit/hr
💡
They Work Best TogetherAPIM → Logic Apps → Functions is a common enterprise pattern: APIM handles security and routing, Logic Apps orchestrates the workflow, Functions executes the complex business logic.

23Pricing Overview

Logic Apps pricing varies dramatically between Consumption (pay-per-action) and Standard (fixed compute) plans, and choosing wrong can mean overpaying by 10x or more. Consumption is cheapest for workflows that run a few times per day, but costs escalate quickly with high-volume loops and enterprise connectors. Standard provides predictable monthly costs and is more economical once you exceed roughly 100,000 actions per month. Always estimate your expected action count, connector types, and run frequency before selecting a plan — and monitor billing metrics after deployment to catch surprises early.

Consumption Plan

ResourcePrice
Actions (first 4,000/month)Free
Actions~$0.000025 per execution
Standard connector calls~$0.000125 per call
Enterprise connector calls~$0.001 per call
B2B messages (AS2/X12)~$0.10–$1.00 per 1,000 messages

Standard Plan

SKUvCPUMemoryPrice (approx)
WS113.5 GB~$190/month
WS227 GB~$380/month
WS3414 GB~$760/month
💰
Cost OptimizationUse stateless workflows for high-throughput scenarios (cheaper on Standard). Batch trigger messages to reduce action counts on Consumption. Use built-in connectors (Standard) instead of managed connectors — no per-call charge.

24Quick Reference Cheat Sheet

This cheat sheet consolidates the most frequently used expressions, Service Bus message properties, and platform limits into a single quick-reference section. Bookmark this for daily development — you will reach for these expressions constantly when building and debugging workflows. The limits table helps you design within platform constraints from the start, avoiding surprises when workflows hit production scale. Print it, pin it, or keep it in a browser tab — these are the values every Logic Apps developer needs at their fingertips.

Key Expressions
text
@triggerBody()?['field']          — Trigger payload field
@body('Action_Name')?['field']     — Action output field
@outputs('Action')?['statusCode'] — HTTP status code
@variables('myVar')               — Variable value
@parameters('myParam')            — Parameter value
@utcNow()                         — Current UTC timestamp
@utcNow('yyyy-MM-dd')             — Formatted date
@guid()                           — New GUID
@workflow()['run']['name']        — Current run ID
@result('Scope_Name')             — Scope result array
@concat('a', 'b', variables('c')) — String concatenation
@coalesce(val1, val2, 'default')  — First non-null value
Service Bus Message Data
text
@triggerBody()?['ContentData']         — Base64 message body
@base64ToString(triggerBody()?['ContentData']) — Decoded body
@triggerBody()?['LockToken']           — Lock token for complete/abandon
@triggerBody()?['MessageId']           — Message ID
@triggerBody()?['SessionId']           — Session ID
@triggerBody()?['CorrelationId']       — Correlation ID
@triggerBody()?['Properties']?['key'] — Custom property
LimitConsumptionStandard
Max workflow duration90 daysUnlimited (stateful)
Max action outputs retained7 daysConfigurable
Max request body size100 MB100 MB
Max For Each concurrency20 parallel20 parallel
Max Until iterations5,0005,000
Max connections per workflowUnlimitedUnlimited
Workflows per app1Unlimited
Run history retention90 daysConfigurable