Skip to content
Get Started for Free

SQL Database

Azure SQL is a managed relational database service for building cloud-native applications with familiar SQL Server tooling. It supports creating logical servers, provisioning databases, and configuring operational features such as firewall access and retention policies. This makes it a common choice for transactional workloads and application backends. For more information, see What is Azure SQL Database?.

LocalStack for Azure provides a local environment for building and testing applications that make use of Azure SQL Database. Each logical server you create is backed by a real SQL Server instance, so your application runs its own T-SQL against a real database engine, and every connection is encrypted with a certificate the client can validate. The supported APIs are listed in the API Coverage section.

This guide is designed for users new to Azure SQL Database and assumes basic knowledge of the Azure CLI and lstk az. The following example creates a SQL server and database, configures firewall access, and defines retention and encryption settings.

Launch LocalStack using your preferred method. For more information, see Introduction to LocalStack for Azure. Once the container is running, enable Azure CLI interception by running:

Terminal window
lstk 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:

Terminal window
lstk az stop-interception

This reconfigures the az CLI to send commands to the official Azure management REST API.

Create a resource group to contain your SQL resources:

Terminal window
az group create --name rg-sql-demo --location westeurope
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sql-demo",
"location": "westeurope",
"name": "rg-sql-demo",
"properties": {
"provisioningState": "Succeeded"
},
...
}

Create a logical SQL server to host your databases:

Terminal window
az sql server create \
--name sqlsrvdoc85 \
--resource-group rg-sql-demo \
--location westeurope \
--admin-user lsadmin \
--admin-password "LocalstackSqlPassw0rd"
Output
{
"administratorLogin": "lsadmin",
...
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sql-demo/providers/Microsoft.Sql/servers/sqlsrvdoc85",
...
"location": "westeurope",
...
"name": "sqlsrvdoc85",
...
"type": "Microsoft.Sql/servers",
...
}

Get the SQL server details to verify it is ready:

Terminal window
az sql server show --name sqlsrvdoc85 --resource-group rg-sql-demo
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sql-demo/providers/Microsoft.Sql/servers/sqlsrvdoc85",
"name": "sqlsrvdoc85",
"location": "westeurope",
"state": "Ready",
"publicNetworkAccess": "Enabled",
"type": "Microsoft.Sql/servers",
...
}

Create a database on the SQL server:

Terminal window
az sql db create \
--name sqldbdoc85 \
--resource-group rg-sql-demo \
--server sqlsrvdoc85 \
--service-objective S0 \
--compute-model Provisioned
Output
{
...
"catalogCollation": "SQL_Latin1_General_CP1_CI_AS",
"collation": "SQL_Latin1_General_CP1_CI_AS",
"creationDate": "2026-03-24T09:32:54.177434+00:00",
"currentBackupStorageRedundancy": "Geo",
"currentServiceObjectiveName": "GP_Gen5_2",
"currentSku": {
"capacity": 2,
"family": "Gen5",
"name": "S0",
"size": null,
"tier": "GeneralPurpose"
},
"databaseId": "62951a4b-e3b7-41ce-b7e7-1d4860801828",
...
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sql-demo/providers/Microsoft.Sql/servers/sqlsrvdoc85/databases/sqldbdoc85",
...
"name": "sqldbdoc85",
...
"sku": {
"capacity": 2,
"family": "Gen5",
"name": "S0",
"size": null,
"tier": "GeneralPurpose"
},
...
"status": "Online",
...
}

Verify the database status to confirm successful creation:

Terminal window
az sql db show \
--name sqldbdoc85 \
--server sqlsrvdoc85 \
--resource-group rg-sql-demo
Output
{
...
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sql-demo/providers/Microsoft.Sql/servers/sqlsrvdoc85/databases/sqldbdoc85",
...
"name": "sqldbdoc85",
...
"status": "Online",
...
}

List the databases on the SQL server:

Terminal window
az sql db list \
--resource-group rg-sql-demo \
--server sqlsrvdoc85
Output
[
{
...
"name": "master",
...
},
{
...
"name": "sqldbdoc85",
...
}
]

Create a firewall rule to allow client access:

Terminal window
az sql server firewall-rule create \
--resource-group rg-sql-demo \
--server sqlsrvdoc85 \
--name AllowLocal \
--start-ip-address 0.0.0.0 \
--end-ip-address 255.255.255.255
Output
{
"name": "AllowLocal",
"startIpAddress": "0.0.0.0",
"endIpAddress": "255.255.255.255",
"type": "Microsoft.Sql/servers/firewallRules",
...
}

Read the endpoint from the server and export it for reuse as the driver’s server value:

Terminal window
export SQL_SERVER=$(az sql server show --name sqlsrvdoc85 --resource-group rg-sql-demo --query fullyQualifiedDomainName --output tsv)
echo "$SQL_SERVER"
Output
sqlsrvdoc85.azure.localhost.localstack.cloud,4510

The endpoint carries the port that the emulator listens on for this server, which is why it is used as it comes. With sqlcmd or any ODBC client, that is the -S or SERVER value:

Terminal window
sqlcmd -S "$SQL_SERVER" -U lsadmin -P "LocalstackSqlPassw0rd" -d sqldbdoc85 -Q "SELECT 1 AS connected"
Output
connected
-----------
1
(1 row affected)

Connections are encrypted and the server certificate validates against the LocalStack public certificate chain, so a client with default settings connects without further configuration, as it does against Azure:

import os
import pyodbc
connection = pyodbc.connect(
"DRIVER={ODBC Driver 18 for SQL Server};"
f"SERVER={os.environ['SQL_SERVER']};"
"DATABASE=sqldbdoc85;UID=lsadmin;"
f"PWD={os.environ['SQL_PASSWORD']};Encrypt=yes;"
)

TrustServerCertificate=yes is not needed. It becomes necessary only when LocalStack cannot download its public certificate, for example with SKIP_SSL_CERT_DOWNLOAD=1 or without outbound network access: the server then presents a certificate issued by the LocalStack root certificate authority and logs a warning naming the server. In that case, either install that root certificate on the client or set TrustServerCertificate=yes.

The firewall rule created in the previous section is what lets this connection through. A logical server accepts no client until something admits it, exactly as on Azure, so without a firewall rule, a virtual network rule or an approved private endpoint the login is refused.

Enable transparent data encryption on the database:

Terminal window
az sql db tde set \
--database sqldbdoc85 \
--server sqlsrvdoc85 \
--resource-group rg-sql-demo \
--status Enabled
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sql-demo/providers/Microsoft.Sql/servers/sqlsrvdoc85/databases/sqldbdoc85/transparentDataEncryption/current",
"name": "current",
"resourceGroup": "rg-sql-demo",
...
"state": "Enabled",
"type": "Microsoft.Sql/servers/databases/transparentDataEncryption"
...
}

Configure a short-term backup retention policy:

Terminal window
az sql db str-policy set \
--name sqldbdoc85 \
--server sqlsrvdoc85 \
--resource-group rg-sql-demo \
--retention-days 7 \
--diffbackup-hours 24
Output
{
"diffBackupIntervalInHours": 24,
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sql-demo/providers/Microsoft.Sql/servers/sqlsrvdoc85/databases/sqldbdoc85/backupShortTermRetentionPolicies/default",
"name": "default",
"resourceGroup": "rg-sql-demo",
"retentionDays": 7,
"type": "Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies"
...
}

Configure a long-term backup retention policy:

Terminal window
az sql db ltr-policy set \
--name sqldbdoc85 \
--server sqlsrvdoc85 \
--resource-group rg-sql-demo \
--weekly-retention "P4W" \
--monthly-retention "P12M" \
--yearly-retention "P5Y" \
--week-of-year 16
Output
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sql-demo/providers/Microsoft.Sql/servers/sqlsrvdoc85/databases/sqldbdoc85/backupLongTermRetentionPolicies/default",
"monthlyRetention": "P12M",
"name": "default",
"resourceGroup": "rg-sql-demo",
"timeBasedImmutability": null,
"timeBasedImmutabilityMode": null,
"type": "Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies",
"weekOfYear": 16,
"weeklyRetention": "P4W",
"yearlyRetention": "P5Y"
...
}

The Azure SQL emulator supports the following features:

  • Server lifecycle management: Create, update, delete, get, and list logical SQL servers.
  • Database CRUD: Create, update, delete, get, list, and rename databases on a logical server.
  • Firewall rules: Create, update, delete, get, and list server-level firewall rules.
  • Transparent data encryption (TDE): Create or update, get, and list TDE configurations per database.
  • Short-term backup retention policies: Create or update, get, update, and list short-term retention policies per database.
  • Long-term backup retention policies: Create or update, get, and list long-term retention policies per database.
  • Database security alert policies: Create or update, get, and list security alert policies per database.
  • Server connection policies: Create or update, get, and list connection policies per server.
  • SQL vulnerability assessments: Create or update, get, and list vulnerability assessment settings per server.
  • Database schema introspection: Get and list schemas, tables, and columns by querying the live SQL Server instance.
  • Server name availability check: Check whether a server name is available for use.
  • Elastic pools: Create, update, delete, get, list, and fail over elastic pools, list the databases in a pool, and move a database in and out of one. A pooled database reports the pool’s tier, and a pool cannot be deleted while a database still belongs to it.
  • Failover groups: Create, update, delete, get, list, and the three failover actions. A database added to a group gets a secondary of the same name on the partner server, and both report the replication link.
  • Server identity: A system-assigned or user-assigned managed identity on the logical server, backed by a real principal that survives a repeated deployment, which is what makes role assignments on it stay valid.
  • Microsoft Entra administrators: Create or update, get, list, and delete the Entra administrator, and enable or disable Entra-only authentication.
  • Virtual network rules: Create or update, get, list, and delete virtual network rules against a subnet with the Microsoft.Sql service endpoint.
  • Private endpoints: Private endpoint connections on the server, including approving and rejecting them, plus the private link resource.
  • Server keys and the encryption protector: Register an Azure Key Vault key on the server and make it the transparent data encryption protector, or return to the service-managed key.
  • Auditing: Server and database blob auditing policies, plain and extended.
  • Advanced threat protection: Server and database advanced threat protection settings, and the server security alert policy.
  • Capabilities and operations: The SKUs and editions available in a location, and the list of operations the provider implements.
  • Database compute management: Update a database in place (PATCH), and pause and resume a serverless database.
  • Restorable dropped databases: Get and list restorable dropped databases (stub: always returns an empty list).
  • Asynchronous provisioning: Server and database creation use async operations with polling headers, matching real Azure behavior.
  • Data does not survive a restart: The SQL Server container is not part of an exported state. After a state import the emulator recreates each server and its databases, and logs a warning that the databases come back empty.
  • The endpoint is not an Azure host name: fullyQualifiedDomainName is {server}.azure.localhost.localstack.cloud,{port}, not {server}.database.windows.net, and it embeds the port. Use the value the API returns rather than building a host name yourself.
  • Network rules are not matched against the client address: The emulator admits a client once the server has any allow path (a firewall rule, a virtual network rule or an approved private endpoint) instead of comparing the client’s address with the rule, because the address it sees is the local machine or the Docker gateway. With publicNetworkAccess disabled, only an approved private endpoint admits. A refused connection is closed before it reaches the engine, so the client reports a connection failure rather than Azure’s login errors 40615 and 47073.
  • minimalTlsVersion is not enforced above TLS 1.2: The value is stored and returned, and the wire allows TLS 1.2, because the SQL Server 2022 image negotiates TLS 1.3 only with TDS 8 strict clients.
  • Microsoft Entra-only authentication is control plane only: The setting is stored, returned and validated, but the engine still accepts the SQL administrator login.
  • Backup retention policies are metadata-only: Short-term and long-term retention policies are stored but no backup or restore is performed.
  • Transparent data encryption is metadata-only: The state, the registered keys and the encryption protector are stored, but no database file is encrypted and no key is used to wrap anything.
  • Security alert policies, vulnerability assessments and advanced threat protection are metadata-only: The settings are stored but no scan runs and no alert is raised.
  • Server connection policies are metadata-only: The policy is stored but does not change how a client reaches the server.
  • A failover group replicates no data: The secondary database is created with the primary’s shape and stays empty, and the replication link reports a healthy state.
  • Elastic pool failover is a no-op: The operation checks the pool and succeeds; there is no replica to fail over to.
  • MSSQL EULA acceptance required: Each logical server runs a Microsoft SQL Server container, so the MSSQL_ACCEPT_EULA environment variable must be set to Y before creating any SQL server. Azure asks for no such acceptance. See Getting started for how to set it.

The behavior of the Azure SQL emulator can be customized using the environment variables listed below.

Variable Description Type Default
MSSQL_ACCEPT_EULA Accept the Microsoft SQL Server End-User Licensing Agreement. Must be set to Y to create SQL servers. On the command line, use LOCALSTACK_MSSQL_ACCEPT_EULA=Y lstk start. String (unset)
ALLOW_MULTIPLE_SQL_SERVER_DEPLOYMENTS Allow provisioning more than one SQL Server Docker container. Set to 1 or true to enable. Boolean 0
LS_AZURE_MSSQL_IMAGE The SQL Server image each logical server runs. String mcr.microsoft.com/mssql/server:2022-latest
SKIP_SSL_CERT_DOWNLOAD Skip downloading the LocalStack public certificate. Servers then present a certificate issued by the LocalStack root certificate authority, so clients need that authority or TrustServerCertificate=yes. Boolean 0

The following samples demonstrate how to use Azure SQL Database with LocalStack for Azure:

111 of 392 operations implemented

Operation ▲Implemented ▼
Page 1 of 0
Was this page helpful?