Azure Logic Apps Storage & Table Connector
Working with Azure Storage Blobs and Tables
Introduction
The Azure Storage connectors in Logic Apps provide powerful capabilities for working with Azure Blob Storage and Azure Table Storage. These connectors enable you to store documents, images, and structured data, making them essential for building data processing workflows.
This comprehensive guide covers:
- Blob operations — Creating, reading, updating, and deleting blobs
- Table operations — Inserting, querying, and managing table entities
- Use cases — Real-world patterns for storage workflows
- Best practices — Performance and security recommendations
Azure Storage Connector Overview
Available Operations
| Operation | Description |
|---|---|
| Blob | Create, Get, Delete, List blobs |
| Table | Insert, Update, Query, Delete entities |
Prerequisites
- Storage Account — Create in Azure Portal
- Connection — Authenticate using:
- Storage Account Key
- Managed Identity (recommended)
- SAS Token
Blob Operations
Create Blob
{
"Create_blob": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "azureblob"
}
},
"method": "post",
"path": "/datasets/default/files",
"queries": {
"folderPath": "orders/@{formatDateTime(utcNow(), 'yyyy-MM-dd')}",
"name": "@concat('order-', triggerBody().orderId, '.json')",
"body": "@json(triggerBody())"
}
}
}
}
Get Blob Content
{
"Get_Blob_Content": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "azureblob"
}
},
"method": "get",
"path": "/datasets/default/content",
"queries": {
"path": "@variables('blobPath')"
}
}
}
}
Get Blob Metadata
{
"Get_Blob_Properties": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "azureblob"
}
},
"method": "get",
"path": "/datasets/default/files",
"queries": {
"path": "@variables('blobPath')"
}
}
}
}
Delete Blob
{
"Delete_Blob": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "azureblob"
}
},
"method": "delete",
"path": "/datasets/default/files",
"queries": {
"path": "@variables('blobPath')"
}
}
}
}
List Blobs
{
"List_Blobs": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "azureblob"
}
},
"method": "get",
"path": "/datasets/default/folders",
"queries": {
"folderPath": "orders"
}
}
}
}
Table Operations
Insert Entity
{
"Insert_Order": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "azurestorageaccount"
}
},
"method": "post",
"path": "/tables/orders/entities",
"body": {
"PartitionKey": "@formatDateTime(utcNow(), 'yyyy-MM')",
"RowKey": "@triggerBody().orderId",
"CustomerName": "@triggerBody().customerName",
"TotalAmount": "@triggerBody().total",
"OrderDate": "@utcNow()",
"Status": "Pending"
}
}
}
}
Update Entity
{
"Update_Order": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "azurestorageaccount"
}
},
"method": "patch",
"path": "/tables/orders/entities(PartitionKey=@encodeUriComponent('@{variables('partitionKey')}'),RowKey=@encodeUriComponent('@{variables('rowKey')}'))",
"body": {
"Status": "Completed",
"CompletedDate": "@utcNow()"
}
}
}
}
Query Entities
{
"Get_Orders_By_Month": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "azurestorageaccount"
}
},
"method": "get",
"path": "/tables/orders/entities",
"queries": {
"$filter": "PartitionKey eq '2024-01'",
"$top": 100
}
}
}
}
Filter Examples
| Filter | Description |
|---|---|
PartitionKey eq '2024-01' | All orders from January 2024 |
Status eq 'Pending' | All pending orders |
TotalAmount ge 100 | Orders over $100 |
contains(CustomerName, 'John') | Orders from customers named John |
Delete Entity
{
"Delete_Order": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "azurestorageaccount"
}
},
"method": "delete",
"path": "/tables/orders/entities(PartitionKey=@encodeUriComponent('@{variables('partitionKey')}'),RowKey=@encodeUriComponent('@{variables('rowKey')}'))"
}
}
}
Use Cases
Use Case 1: Order Processing Pipeline
┌─────────────────────────────────────────────────────────────────────┐
│ ORDER PROCESSING PIPELINE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Service Bus Trigger │
│ │ └─ Receives new order │
│ │ │
│ 2. Insert into Table │
│ │ └─ PartitionKey: Year-Month │
│ │ └─ RowKey: Order ID │
│ │ └─ Metadata: Customer, Total, Status │
│ │ │
│ 3. Create Blob │
│ │ └─ Path: orders/2024-01/order-123.json │
│ │ └─ Body: Complete order JSON │
│ │ │
│ 4. Send Email Notification │
│ │ └─ Notify customer of successful order │
│ │ │
└─────────────────────────────────────────────────────────────────────┘
{
"definition": {
"triggers": {
"When_message_received": {
"type": "ServiceBus",
"inputs": {
"topic": "orders-topic",
"subscription": "processor"
}
}
},
"actions": {
"Insert_Order_Metadata": {
"type": "AzureTable",
"inputs": {
"method": "post",
"path": "/tables/orders/entities",
"body": {
"PartitionKey": "@formatDateTime(utcNow(), 'yyyy-MM')",
"RowKey": "@triggerBody().orderId",
"CustomerId": "@triggerBody().customerId",
"Total": "@triggerBody().total",
"Status": "Received"
}
}
},
"Save_Order_JSON": {
"type": "AzureBlob",
"inputs": {
"method": "post",
"path": "/datasets/default/files",
"queries": {
"folderPath": "orders/@formatDateTime(utcNow(), 'yyyy-MM-dd')",
"name": "@concat(triggerBody().orderId, '.json')",
"body": "@triggerBody()"
}
}
},
"Send_Confirmation": {
"type": "Office365",
"inputs": {
"method": "post",
"path": "/v2.0/me/sendMail",
"body": {
"message": {
"subject": "Order Confirmed",
"body": {
"contentType": "HTML",
"content": "<p>Your order has been received!</p>"
}
}
}
}
}
}
}
}
Use Case 2: File Archival Workflow
- Trigger: Timer (every day at midnight)
- List Old Blobs: Find blobs older than 90 days
- Copy to Archive: Move to archive container
- Delete Original: Remove from source container
- Log to Table: Record archival operation
Use Case 3: Data Export
- Trigger: HTTP request
- Query Table: Get filtered entities
- Convert to CSV: Transform to CSV format
- Create Blob: Save as CSV file
- Return URL: Send download link to user
Managed Identity Authentication
Enable Managed Identity
# Enable system-assigned identity
az logicapp update \
--name my-logic-app \
--resource-group my-rg \
--identity systemassigned
Assign Storage Role
# Grant blob access
az role assignment create \
--assignee <logic-app-principal-id> \
--role "Storage Blob Data Contributor" \
--scope "/subscriptions/xxx/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/mystorage"
# Grant table access
az role assignment create \
--assignee <logic-app-principal-id> \
--role "Storage Table Data Contributor" \
--scope "/subscriptions/xxx/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/mystorage"
Best Practices
| Practice | Description |
|---|---|
| Use Managed Identity | Avoid storing connection strings |
| Partition Key Design | Choose keys for efficient queries |
| Batch Operations | Use batch when possible |
| Error Handling | Implement retry and dead-lettering |
| Logging | Track operations for debugging |
Performance Tips
- Use appropriate partitions for Table storage
- Limit results with $top and pagination
- Cache connection references
- Use asynchronous operations for large files
Related Topics
- Service Bus Connector — Message-based triggers
- Azure Functions — Serverless integration
- Blob Storage — Storage fundamentals
Azure Integration Hub - Intermediate Level