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

OperationDescription
BlobCreate, Get, Delete, List blobs
TableInsert, Update, Query, Delete entities

Prerequisites

  1. Storage Account — Create in Azure Portal
  2. 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

FilterDescription
PartitionKey eq '2024-01'All orders from January 2024
Status eq 'Pending'All pending orders
TotalAmount ge 100Orders 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

  1. Trigger: Timer (every day at midnight)
  2. List Old Blobs: Find blobs older than 90 days
  3. Copy to Archive: Move to archive container
  4. Delete Original: Remove from source container
  5. Log to Table: Record archival operation

Use Case 3: Data Export

  1. Trigger: HTTP request
  2. Query Table: Get filtered entities
  3. Convert to CSV: Transform to CSV format
  4. Create Blob: Save as CSV file
  5. 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

PracticeDescription
Use Managed IdentityAvoid storing connection strings
Partition Key DesignChoose keys for efficient queries
Batch OperationsUse batch when possible
Error HandlingImplement retry and dead-lettering
LoggingTrack 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


Azure Integration Hub - Intermediate Level