From 35f8e7f39e141bc35ef994934a9971b1518139b8 Mon Sep 17 00:00:00 2001 From: HarshCasper Date: Fri, 27 Feb 2026 19:09:16 +0530 Subject: [PATCH 1/4] add Azure Table Storage (legacy api) service doc --- .../docs/azure/services/table-storage.mdx | 217 +++++++++++++++++- 1 file changed, 216 insertions(+), 1 deletion(-) diff --git a/src/content/docs/azure/services/table-storage.mdx b/src/content/docs/azure/services/table-storage.mdx index fe8c3616..3912d070 100644 --- a/src/content/docs/azure/services/table-storage.mdx +++ b/src/content/docs/azure/services/table-storage.mdx @@ -1,11 +1,226 @@ --- title: "Table Storage" -description: API coverage for Microsoft.TableStorage in LocalStack for Azure. +description: Get started with Azure Table Storage in LocalStack template: doc --- import AzureFeatureCoverage from "../../../../components/feature-coverage/AzureFeatureCoverage"; +## Introduction + +Azure Table Storage is a NoSQL key-value store for large volumes of semi-structured data. +With the legacy Table API, data is organized into tables, partitions, and entities addressed by `PartitionKey` and `RowKey`. +It is useful for lightweight metadata, lookup records, and simple operational datasets. + +LocalStack for Azure lets you build and test Table Storage workflows locally using the same CLI flow as cloud environments. +The supported APIs are listed in the [API Coverage](#api-coverage) section. + +## Getting started + +This guide is designed for users new to Azure Table Storage and assumes basic knowledge of the Azure CLI and `azlocal`. + +Start by enabling interception so your `az` commands are routed to LocalStack: + +```bash +azlocal start_interception +``` + +The following example creates a storage account, creates a table, and performs basic entity operations. + +### Create a resource group + +Create a resource group for the storage resources: + +```bash +az group create --name rg-table-legacy-demo --location westeurope +``` + +```bash title="Output" +{ + "name": "rg-table-legacy-demo", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-table-legacy-demo", + "location": "westeurope", + "properties": { + "provisioningState": "Succeeded" + }, + ... +} +``` + +### Create a storage account + +Create a storage account that will host the table service: + +```bash +az storage account create \ + --name stordoc88acct \ + --resource-group rg-table-legacy-demo \ + --location westeurope \ + --sku Standard_LRS \ + --kind StorageV2 +``` + +```bash title="Output" +{ + "name": "stordoc88acct", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-table-legacy-demo/providers/Microsoft.Storage/storageAccounts/stordoc88acct", + "location": "westeurope", + "kind": "StorageV2", + "provisioningState": "Succeeded", + "primaryEndpoints": { + "table": "https://stordoc88accttable.localhost.localstack.cloud:4566", + ... + }, + ... +} +``` + +### Create and inspect a table + +Get the storage account connection string used for data-plane operations: + +```bash +CONNECTION_STRING=$(az storage account show-connection-string \ + --name stordoc88acct \ + --resource-group rg-table-legacy-demo \ + --query connectionString -o tsv) +``` + +Create a table: + +```bash +az storage table create --name legacytable --connection-string "$CONNECTION_STRING" +``` + +```bash title="Output" +{ + "created": true +} +``` + +Check whether the table exists: + +```bash +az storage table exists --name legacytable --connection-string "$CONNECTION_STRING" +``` + +```bash title="Output" +{ + "exists": true +} +``` + +### Insert and query entities + +Insert an entity into the table: + +```bash +az storage entity insert \ + --connection-string "$CONNECTION_STRING" \ + --table-name legacytable \ + --entity PartitionKey=demo RowKey=1 name=Alice score=100 +``` + +```bash title="Output" +{ + "content": { + "PartitionKey": "demo", + "RowKey": "1", + "name": "Alice", + "score": 100, + ... + }, + "etag": "W/\"datetime'2026-02-27T11%3A37%3A25.7298901Z'\"", + ... +} +``` + +Get the inserted entity: + +```bash +az storage entity show \ + --connection-string "$CONNECTION_STRING" \ + --table-name legacytable \ + --partition-key demo \ + --row-key 1 +``` + +```bash title="Output" +{ + "PartitionKey": "demo", + "RowKey": "1", + "name": "Alice", + "score": 100, + ... +} +``` + +Query entities by partition key: + +```bash +az storage entity query \ + --connection-string "$CONNECTION_STRING" \ + --table-name legacytable \ + --filter "PartitionKey eq 'demo'" +``` + +```bash title="Output" +{ + "items": [ + { + "PartitionKey": "demo", + "RowKey": "1", + "name": "Alice", + "score": 100, + ... + } + ], + "nextMarker": {} +} +``` + +### Update, delete, and verify + +Update the entity with a merge operation: + +```bash +az storage entity merge \ + --connection-string "$CONNECTION_STRING" \ + --table-name legacytable \ + --entity PartitionKey=demo RowKey=1 score=101 +``` + +```bash title="Output" +{ + "etag": "W/\"datetime'2026-02-27T11%3A37%3A27.3795415Z'\"", + ... +} +``` + +Delete the entity and verify the table is empty: + +```bash +az storage entity delete \ + --connection-string "$CONNECTION_STRING" \ + --table-name legacytable \ + --partition-key demo \ + --row-key 1 + +az storage entity query \ + --connection-string "$CONNECTION_STRING" \ + --table-name legacytable +``` + +```bash title="Output" +{ + "deleted": null +} +{ + "items": [], + "nextMarker": {} +} +``` + ## API Coverage From d74e1613888a304d38ec5ffc02f5e8653a22a0d6 Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Wed, 4 Mar 2026 11:43:47 +0100 Subject: [PATCH 2/4] Extend Azure Table Storage article --- .../docs/azure/services/table-storage.mdx | 216 ++++++++++++------ 1 file changed, 151 insertions(+), 65 deletions(-) diff --git a/src/content/docs/azure/services/table-storage.mdx b/src/content/docs/azure/services/table-storage.mdx index 3912d070..449671ff 100644 --- a/src/content/docs/azure/services/table-storage.mdx +++ b/src/content/docs/azure/services/table-storage.mdx @@ -8,88 +8,132 @@ import AzureFeatureCoverage from "../../../../components/feature-coverage/AzureF ## Introduction -Azure Table Storage is a NoSQL key-value store for large volumes of semi-structured data. -With the legacy Table API, data is organized into tables, partitions, and entities addressed by `PartitionKey` and `RowKey`. -It is useful for lightweight metadata, lookup records, and simple operational datasets. +Azure Table Storage is a NoSQL key-value store designed for large volumes of semi-structured data, useful for lightweight metadata, lookup records, and simple operational datasets. +Data is organized into tables, partitions, and entities addressed by PartitionKey and RowKey. +It offers schemaless flexibility at a fraction of the cost of traditional SQL, making it easy to adapt as your application evolves. For more information, see [What is Azure Table storage?](https://learn.microsoft.com/en-us/azure/storage/tables/table-storage-overview) -LocalStack for Azure lets you build and test Table Storage workflows locally using the same CLI flow as cloud environments. -The supported APIs are listed in the [API Coverage](#api-coverage) section. +LocalStack for Azure provides a local environment for building and testing applications that make use of Azure Table Storage. +The supported APIs are available on our [API Coverage section](#api-coverage), which provides information on the extent of Table Storage's integration with LocalStack. ## Getting started -This guide is designed for users new to Azure Table Storage and assumes basic knowledge of the Azure CLI and `azlocal`. +This guide is designed for users new to Table Storage and assumes basic knowledge of the Azure CLI and our `azlocal` wrapper script. -Start by enabling interception so your `az` commands are routed to LocalStack: +Start your LocalStack container using your preferred method. For more information, see [Introduction to LocalStack for Azure](/azure/getting-started/). -```bash -azlocal start_interception -``` - -The following example creates a storage account, creates a table, and performs basic entity operations. +> [!NOTE] +> As an alternative to using the `azlocal` CLI, customers can run `az start-interception`. This command points the `az` CLI away from the public Azure cloud management API and toward the local emulator API. +To revert this configuration, use `azlocal stop-interception`, which re-configures the CLI to send commands to the official Azure platform management REST API. +At this time, there is no full parity between `azlocal` commands and `az` commands after running `az start-interception`. Therefore, this technique is not fully interchangeable. ### Create a resource group -Create a resource group for the storage resources: +Create a resource group to contain your storage resources: ```bash -az group create --name rg-table-legacy-demo --location westeurope +azlocal group create \ + --name rg-table-demo \ + --location westeurope ``` ```bash title="Output" { - "name": "rg-table-legacy-demo", - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-table-legacy-demo", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-table-demo", "location": "westeurope", + "managedBy": null, + "name": "rg-table-demo", "properties": { "provisioningState": "Succeeded" }, - ... + "tags": null, + "type": "Microsoft.Resources/resourceGroups" } ``` ### Create a storage account -Create a storage account that will host the table service: +Create a storage account in the resource group: ```bash -az storage account create \ - --name stordoc88acct \ - --resource-group rg-table-legacy-demo \ +azlocal storage account create \ + --name sttabledemols \ + --resource-group rg-table-demo \ --location westeurope \ - --sku Standard_LRS \ - --kind StorageV2 + --sku Standard_LRS ``` ```bash title="Output" { - "name": "stordoc88acct", - "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-table-legacy-demo/providers/Microsoft.Storage/storageAccounts/stordoc88acct", - "location": "westeurope", - "kind": "StorageV2", - "provisioningState": "Succeeded", + ... + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-table-demo/providers/Microsoft.Storage/storageAccounts/sttabledemols", + ... + "name": "sttabledemols", + ... + "placement": null, "primaryEndpoints": { - "table": "https://stordoc88accttable.localhost.localstack.cloud:4566", + "blob": "https://sttabledemolsblob.localhost.localstack.cloud:4566", + ... + "table": "https://sttabledemolstable.localhost.localstack.cloud:4566", ... }, - ... + .... } ``` -### Create and inspect a table +### Authentication + +There are three ways to authenticate storage table commands against the emulator: + +#### Storage account key + +Retrieve the account key and pass it with `--account-name` and `--account-key`: + +```bash +ACCOUNT_KEY=$(azlocal storage account keys list \ + --account-name sttabledemols \ + --resource-group rg-table-demo \ + --query "[0].value" \ + --output tsv) + +azlocal storage table list \ + --account-name sttabledemols \ + --account-key "$ACCOUNT_KEY" +``` + +#### Login credentials + +Use `--auth-mode login` to authenticate with the current session credentials: + +```bash +azlocal storage table list \ + --account-name sttabledemols \ + --auth-mode login +``` + +#### Connection string -Get the storage account connection string used for data-plane operations: +Bundle the account name and key into a single value: ```bash -CONNECTION_STRING=$(az storage account show-connection-string \ - --name stordoc88acct \ - --resource-group rg-table-legacy-demo \ +CONNECTION_STRING=$(azlocal storage account show-connection-string \ + --name sttabledemols \ + --resource-group rg-table-demo \ --query connectionString -o tsv) + +azlocal storage table list \ + --connection-string "$CONNECTION_STRING" ``` +The remaining examples in this guide use connection strings for brevity. + +### Create and inspect a table + Create a table: ```bash -az storage table create --name legacytable --connection-string "$CONNECTION_STRING" +azlocal storage table create \ + --name apptable \ + --connection-string "$CONNECTION_STRING" ``` ```bash title="Output" @@ -98,10 +142,12 @@ az storage table create --name legacytable --connection-string "$CONNECTION_STRI } ``` -Check whether the table exists: +Verify the table exists: ```bash -az storage table exists --name legacytable --connection-string "$CONNECTION_STRING" +azlocal storage table exists \ + --name apptable \ + --connection-string "$CONNECTION_STRING" ``` ```bash title="Output" @@ -110,15 +156,30 @@ az storage table exists --name legacytable --connection-string "$CONNECTION_STRI } ``` +List tables in the storage account: + +```bash +azlocal storage table list \ + --connection-string "$CONNECTION_STRING" +``` + +```bash title="Output" +[ + { + "name": "apptable" + } +] +``` + ### Insert and query entities Insert an entity into the table: ```bash -az storage entity insert \ - --connection-string "$CONNECTION_STRING" \ - --table-name legacytable \ - --entity PartitionKey=demo RowKey=1 name=Alice score=100 +azlocal storage entity insert \ + --table-name apptable \ + --entity PartitionKey=demo RowKey=1 name=Alice score=100 \ + --connection-string "$CONNECTION_STRING" ``` ```bash title="Output" @@ -130,19 +191,19 @@ az storage entity insert \ "score": 100, ... }, - "etag": "W/\"datetime'2026-02-27T11%3A37%3A25.7298901Z'\"", + "etag": "W/\"datetime'...'\"", ... } ``` -Get the inserted entity: +Retrieve the entity by its partition key and row key: ```bash -az storage entity show \ - --connection-string "$CONNECTION_STRING" \ - --table-name legacytable \ +azlocal storage entity show \ + --table-name apptable \ --partition-key demo \ - --row-key 1 + --row-key 1 \ + --connection-string "$CONNECTION_STRING" ``` ```bash title="Output" @@ -158,10 +219,10 @@ az storage entity show \ Query entities by partition key: ```bash -az storage entity query \ - --connection-string "$CONNECTION_STRING" \ - --table-name legacytable \ - --filter "PartitionKey eq 'demo'" +azlocal storage entity query \ + --table-name apptable \ + --filter "PartitionKey eq 'demo'" \ + --connection-string "$CONNECTION_STRING" ``` ```bash title="Output" @@ -179,20 +240,20 @@ az storage entity query \ } ``` -### Update, delete, and verify +### Update, merge, and delete entities Update the entity with a merge operation: ```bash -az storage entity merge \ - --connection-string "$CONNECTION_STRING" \ - --table-name legacytable \ - --entity PartitionKey=demo RowKey=1 score=101 +azlocal storage entity merge \ + --table-name apptable \ + --entity PartitionKey=demo RowKey=1 score=101 \ + --connection-string "$CONNECTION_STRING" ``` ```bash title="Output" { - "etag": "W/\"datetime'2026-02-27T11%3A37%3A27.3795415Z'\"", + "etag": "W/\"datetime'...'\"", ... } ``` @@ -200,15 +261,15 @@ az storage entity merge \ Delete the entity and verify the table is empty: ```bash -az storage entity delete \ - --connection-string "$CONNECTION_STRING" \ - --table-name legacytable \ +azlocal storage entity delete \ + --table-name apptable \ --partition-key demo \ - --row-key 1 + --row-key 1 \ + --connection-string "$CONNECTION_STRING" -az storage entity query \ - --connection-string "$CONNECTION_STRING" \ - --table-name legacytable +azlocal storage entity query \ + --table-name apptable \ + --connection-string "$CONNECTION_STRING" ``` ```bash title="Output" @@ -221,6 +282,31 @@ az storage entity query \ } ``` +## Features + +The Table Storage emulator supports the following features: + +- **Data plane REST API**: Table CRUD, entity operations (insert, query, merge, replace, delete), OData query filters, and batch/transaction requests. +- **Control plane REST API**: Create and get tables, get and set table service properties via Azure Resource Manager. +- **Multiple authentication modes**: Storage account key, login credentials, and connection strings. +- **Entity operations**: Insert, query, show, merge, replace, and delete entities with schemaless, key-value data addressed by `PartitionKey` and `RowKey`. +- **OData query support**: Filter and project entities using OData expressions (e.g., `PartitionKey eq 'demo'`). +- **Batch operations**: Entity batch (transaction) requests are proxied with correct URL and authorization rewriting. + +## Limitations + +- **No data persistence across restarts**: Table data is not persisted and is lost when the LocalStack emulator is stopped or restarted. +- **Table service properties**: `set_service_properties` is a no-op and `get_service_properties` returns empty defaults, unlike Azure where CORS, logging, and metrics settings are persisted and applied. +- **Storage account keys**: Keys are emulator-generated rather than managed by Azure. +- **Header validation**: Unsupported request headers or parameters are silently accepted (Azurite runs in loose mode) instead of being rejected. +- **API version enforcement**: The emulator does not validate the `x-ms-version` header; all API versions are accepted. + +## Samples + +The following sample demonstrates how to use Table Storage with LocalStack for Azure: + +- [Azure Functions Sample with LocalStack for Azure](https://github.com/localstack/localstack-azure-samples/tree/main/samples/function-app-storage-http/dotnet) + ## API Coverage From e159fbce6b48e62b30ae9478b83901613d00743a Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Wed, 4 Mar 2026 15:32:46 +0100 Subject: [PATCH 3/4] Fix azlocal note --- src/content/docs/azure/services/table-storage.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/content/docs/azure/services/table-storage.mdx b/src/content/docs/azure/services/table-storage.mdx index 449671ff..9ffce0c5 100644 --- a/src/content/docs/azure/services/table-storage.mdx +++ b/src/content/docs/azure/services/table-storage.mdx @@ -21,10 +21,11 @@ This guide is designed for users new to Table Storage and assumes basic knowledg Start your LocalStack container using your preferred method. For more information, see [Introduction to LocalStack for Azure](/azure/getting-started/). -> [!NOTE] -> As an alternative to using the `azlocal` CLI, customers can run `az start-interception`. This command points the `az` CLI away from the public Azure cloud management API and toward the local emulator API. +:::note +As an alternative to using the `azlocal` CLI, customers can run `az start-interception`. This command points the `az` CLI away from the public Azure cloud management API and toward the local emulator API. To revert this configuration, use `azlocal stop-interception`, which re-configures the CLI to send commands to the official Azure platform management REST API. At this time, there is no full parity between `azlocal` commands and `az` commands after running `az start-interception`. Therefore, this technique is not fully interchangeable. +::: ### Create a resource group From da140a90dbcbaf4ab40c136e22ebc6e7becb30b1 Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Thu, 5 Mar 2026 08:26:42 +0100 Subject: [PATCH 4/4] Improve node wording --- src/content/docs/azure/services/table-storage.mdx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/content/docs/azure/services/table-storage.mdx b/src/content/docs/azure/services/table-storage.mdx index 9ffce0c5..42df138c 100644 --- a/src/content/docs/azure/services/table-storage.mdx +++ b/src/content/docs/azure/services/table-storage.mdx @@ -22,9 +22,16 @@ This guide is designed for users new to Table Storage and assumes basic knowledg Start your LocalStack container using your preferred method. For more information, see [Introduction to LocalStack for Azure](/azure/getting-started/). :::note -As an alternative to using the `azlocal` CLI, customers can run `az start-interception`. This command points the `az` CLI away from the public Azure cloud management API and toward the local emulator API. -To revert this configuration, use `azlocal stop-interception`, which re-configures the CLI to send commands to the official Azure platform management REST API. -At this time, there is no full parity between `azlocal` commands and `az` commands after running `az start-interception`. Therefore, this technique is not fully interchangeable. +As an alternative to using the `azlocal` CLI, users can run: + +`az start-interception` + +This command points the `az` CLI away from the public Azure management REST API and toward the LocalStack for Azure emulator API. +To revert this configuration, run: + +`azlocal stop-interception` + +This reconfigures the `az` CLI to send commands to the official Azure management REST API. At this time, there is no full parity between `azlocal` and `az` commands after running `az start-interception`. Therefore, this technique is not fully interchangeable. ::: ### Create a resource group