SQL Database
Introduction
Section titled “Introduction”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.
Getting started
Section titled “Getting started”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:
lstk az start-interceptionThis 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:
lstk az stop-interceptionThis reconfigures the az CLI to send commands to the official Azure management REST API.
Create a resource group
Section titled “Create a resource group”Create a resource group to contain your SQL resources:
az group create --name rg-sql-demo --location westeurope{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-sql-demo", "location": "westeurope", "name": "rg-sql-demo", "properties": { "provisioningState": "Succeeded" }, ...}Create and inspect a SQL server
Section titled “Create and inspect a SQL server”Create a logical SQL server to host your databases:
az sql server create \ --name sqlsrvdoc85 \ --resource-group rg-sql-demo \ --location westeurope \ --admin-user lsadmin \ --admin-password "LocalstackSqlPassw0rd"{ "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:
az sql server show --name sqlsrvdoc85 --resource-group rg-sql-demo{ "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 and query a database
Section titled “Create and query a database”Create a database on the SQL server:
az sql db create \ --name sqldbdoc85 \ --resource-group rg-sql-demo \ --server sqlsrvdoc85 \ --service-objective S0 \ --compute-model Provisioned{ ... "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:
az sql db show \ --name sqldbdoc85 \ --server sqlsrvdoc85 \ --resource-group rg-sql-demo{ ... "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:
az sql db list \ --resource-group rg-sql-demo \ --server sqlsrvdoc85[ { ... "name": "master", ... }, { ... "name": "sqldbdoc85", ... }]Add a firewall rule
Section titled “Add a firewall rule”Create a firewall rule to allow client access:
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{ "name": "AllowLocal", "startIpAddress": "0.0.0.0", "endIpAddress": "255.255.255.255", "type": "Microsoft.Sql/servers/firewallRules", ...}Connect to a database
Section titled “Connect to a database”Read the endpoint from the server and export it for reuse as the driver’s server value:
export SQL_SERVER=$(az sql server show --name sqlsrvdoc85 --resource-group rg-sql-demo --query fullyQualifiedDomainName --output tsv)echo "$SQL_SERVER"sqlsrvdoc85.azure.localhost.localstack.cloud,4510The 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:
sqlcmd -S "$SQL_SERVER" -U lsadmin -P "LocalstackSqlPassw0rd" -d sqldbdoc85 -Q "SELECT 1 AS connected"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 osimport 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.
Configure transparent data encryption
Section titled “Configure transparent data encryption”Enable transparent data encryption on the database:
az sql db tde set \ --database sqldbdoc85 \ --server sqlsrvdoc85 \ --resource-group rg-sql-demo \ --status Enabled{ "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 backup retention policies
Section titled “Configure backup retention policies”Configure a short-term backup retention policy:
az sql db str-policy set \ --name sqldbdoc85 \ --server sqlsrvdoc85 \ --resource-group rg-sql-demo \ --retention-days 7 \ --diffbackup-hours 24{ "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:
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{ "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"...}Features
Section titled “Features”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.Sqlservice 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.
Limitations
Section titled “Limitations”- 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:
fullyQualifiedDomainNameis{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
publicNetworkAccessdisabled, 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. minimalTlsVersionis 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_EULAenvironment variable must be set toYbefore creating any SQL server. Azure asks for no such acceptance. See Getting started for how to set it.
Configuration
Section titled “Configuration”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 |
Samples
Section titled “Samples”The following samples demonstrate how to use Azure SQL Database with LocalStack for Azure:
- Web App and SQL Database (Python)
- Web App and SQL Database (.NET)
- Web App on AKS and SQL Database (Python)
- Web App on AKS and SQL Database (.NET)
API Coverage
Section titled “API Coverage”111 of 392 operations implemented
| Operation ▲ | Implemented ▼ |
|---|