---
title: "Set up Azure SQL Database | Database Observability documentation"
description: "Set up Database Observability for Azure SQL Database using Grafana Alloy and send telemetry to Grafana Cloud."
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Set up Azure SQL Database

Set up Database Observability with Grafana Cloud to collect telemetry from Azure SQL Database using Grafana Alloy. You configure your Azure SQL database and Alloy to forward telemetry to Grafana Cloud.

If you already use the SQL Server integration, Database Observability extends it with query-level telemetry collected by the `database_observability.sql_server` Alloy component.

## What you’ll achieve

In this article, you:

- Confirm Query Store is enabled on the database you want to monitor.
- Create a contained monitoring user with the required privileges.
- Configure Alloy with the Database Observability components.
- Forward telemetry to Grafana Cloud.
- Verify that telemetry appears in Database Observability.

## Setup steps

Setting up Database Observability for Azure SQL Database has three steps:

1. [**Set up your database**](https://grafana.com/docs/grafana-cloud/observe-and-act/monitor-infrastructure/database-observability/set-up/sqlserver/azure-sql-database/#set-up-your-database): Prepare your Azure SQL database so Alloy can collect from it.
2. [**Configure Grafana Alloy**](https://grafana.com/docs/grafana-cloud/observe-and-act/monitor-infrastructure/database-observability/set-up/sqlserver/azure-sql-database/#configure-grafana-alloy): Configure how Alloy collects telemetry and sends it to Grafana Cloud.
3. [**Verify telemetry in Grafana Cloud**](https://grafana.com/docs/grafana-cloud/observe-and-act/monitor-infrastructure/database-observability/set-up/sqlserver/azure-sql-database/#verify-telemetry-in-grafana-cloud): Check telemetry status and confirm that query metrics appear in Database Observability.

## Before you begin

To complete this setup, you need:

- An Azure SQL Database with Query Store available.
- A server administrator, or a user that can create users and grant privileges in the database you want to monitor.
- The fully qualified server name, for example `<SERVER_NAME>.database.windows.net`, and the name of the database you want to monitor.
- A planned [Grafana Alloy](https://grafana.com/docs/grafana-cloud/send-data/alloy/) deployment location with network access to your Azure SQL Database endpoint on port `1433`.

Estimated setup time: 15-30 minutes.

> Note
> 
> Alloy should connect directly to the database host. Avoid connecting Alloy to the database through a load balancer or connection pooler as it would limit Alloy’s ability to collect accurate telemetry.

## Set up your database

> Important
> 
> On Azure SQL Database, the `USE` statement can’t switch between databases. Point each connection’s `data_source_name` at one specific user database, never at `master`. Schema details, query metrics, and query text then all cover that single database. To monitor several databases on the same logical server, add one [`database_instance`](https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/database_observability/database_observability.sql_server/#database_instance) block per database in a single `database_observability.sql_server` component, each with its own `data_source_name`.

In this step, you’ll prepare your Azure SQL database for monitoring by confirming Query Store is enabled, creating a monitoring user, and granting the permissions Database Observability needs.

Complete this before configuring Alloy. Without it, Alloy can connect to your database, but it won’t be able to collect the telemetry required for Database Observability.

### Enable Query Store

Query Store is the per-database feature Database Observability reads for query metrics and query text. On Azure SQL Database, Query Store is on by default, so you usually only need to confirm it’s writable.

Connect to the database you want to monitor and check the Query Store state:

SQL ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```sql
SELECT actual_state_desc FROM sys.database_query_store_options;
```

The `actual_state_desc` column should return `READ_WRITE`. If it returns `READ_ONLY` or `OFF`, re-enable Query Store on the connected database:

SQL ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```sql
ALTER DATABASE CURRENT SET QUERY_STORE = ON (OPERATION_MODE = READ_WRITE);
```

On Azure SQL Database you can’t name another database in `ALTER DATABASE`. Use `ALTER DATABASE CURRENT` while connected to the database you want to change.

### Create a monitoring user and grant privileges

Connect to the database you want to monitor, not `master`, as an administrator and create a contained monitoring user named `db-o11y`:

SQL ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```sql
CREATE USER [db-o11y] WITH PASSWORD = '<DB_O11Y_PASSWORD>';
GRANT CONNECT             TO [db-o11y];
GRANT VIEW DEFINITION     TO [db-o11y]; -- schema metadata
GRANT VIEW DATABASE STATE TO [db-o11y]; -- Query Store, database resource metrics, and session activity
```

Replace *&lt;DB\_O11Y\_PASSWORD&gt;* with a strong password.

Repeat this in every database you want to monitor. Because `USE` can’t switch databases on Azure SQL Database, each database needs its own contained user and its own `data_source_name`.

### Verify user privileges

Connect with the `db-o11y` credentials, not the administrator, against the database you want to monitor, then confirm the effective privileges:

SQL ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```sql
-- Query Store is readable on the connected database. Expect one row with actual_state_desc = READ_WRITE.
SELECT DB_NAME() AS database_name, actual_state_desc FROM sys.database_query_store_options;

-- Effective permissions on the connected database. Expect 1 for both columns.
SELECT
  HAS_PERMS_BY_NAME(DB_NAME(), 'DATABASE', 'VIEW DEFINITION') AS can_view_definition,
  HAS_PERMS_BY_NAME(DB_NAME(), 'DATABASE', 'VIEW DATABASE STATE') AS can_view_database_state;
```

If the first query returns no rows or an error, or either permission check returns `0`, re-run the grants in [Create a monitoring user and grant privileges](https://grafana.com/docs/grafana-cloud/observe-and-act/monitor-infrastructure/database-observability/set-up/sqlserver/azure-sql-database/#create-a-monitoring-user-and-grant-privileges) while connected to that user database.

### Database setup checkpoint

Continue to Alloy configuration only after these conditions are true:

- Query Store is `READ_WRITE` on the database you point Alloy at (`SELECT actual_state_desc FROM sys.database_query_store_options;` returns `READ_WRITE`).
- The `db-o11y` contained user exists in that database and has `VIEW DATABASE STATE` and `VIEW DEFINITION`.
- The [Verify user privileges](https://grafana.com/docs/grafana-cloud/observe-and-act/monitor-infrastructure/database-observability/set-up/sqlserver/azure-sql-database/#verify-user-privileges) queries confirm the grants are effective as `db-o11y`.
- The `db-o11y` user can connect from the network where Alloy will run, on port `1433`.

After these checks pass, your Azure SQL database is ready for Database Observability. Next, configure Alloy so it can collect telemetry from the database endpoint and send it to Grafana Cloud.

## Configure Grafana Alloy

After you set up your database, configure Alloy to collect telemetry and send it to Grafana Cloud. These instructions use a custom Alloy configuration file, which you manage outside the Database Observability setup flow in Grafana Cloud.

### Make sure you’re on a supported Alloy version

Alloy `1.22.0` or later is required for Database Observability for SQL Server. Find the latest stable version on [Docker Hub](https://hub.docker.com/r/grafana/alloy/tags). To update, refer to the [Alloy release notes](https://github.com/grafana/alloy/releases).

> Note
> 
> New to Alloy?
> 
> [Grafana Alloy](https://grafana.com/docs/grafana-cloud/send-data/alloy/introduction/) is an open source collector that sends your data to Grafana Cloud. Database Observability needs it to collect metrics and query telemetry from your database.
> 
> If you don’t have it installed, refer to [Install Grafana Alloy](https://grafana.com/docs/grafana-cloud/send-data/alloy/set-up/install/) before you continue.

### Add the Azure SQL Database configuration blocks

Add these blocks to Alloy for Azure SQL Database. Replace *&lt;DB\_NAME&gt;*. Create a `local.file` with the data source name string, for example, `"sqlserver://<DB_O11Y_USER>:<DB_O11Y_PASSWORD>@<SERVER_FQDN>:<DB_PORT>?database=<DB_DATABASE>&encrypt=true"`:

Alloy ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
local.file "sqlserver_secret_<DB_NAME>" {
  filename  = "/var/lib/alloy/sqlserver_secret_<DB_NAME>"
  is_secret = true
}

database_observability.sql_server "sqlserver_<DB_NAME>" {
  data_source_name = local.file.sqlserver_secret_<DB_NAME>.content
  forward_to       = [loki.relabel.database_observability_sqlserver_<DB_NAME>.receiver]

  cloud_provider {
    azure {
      subscription_id = "<AZURE_SUBSCRIPTION_ID>"
      resource_group  = "<AZURE_RESOURCE_GROUP>"
      server_name     = "<AZURE_SERVER_NAME>"
    }
  }
}

loki.relabel "database_observability_sqlserver_<DB_NAME>" {
  forward_to = [loki.write.grafana_cloud_loki.receiver]

  rule {
    target_label = "instance"
    replacement  = "<INSTANCE_LABEL>"
  }
}

discovery.relabel "database_observability_sqlserver_<DB_NAME>" {
  targets = database_observability.sql_server.sqlserver_<DB_NAME>.targets

  rule {
    target_label = "job"
    replacement  = "integrations/db-o11y"
  }

  // OPTIONAL: relabel `instance` to `dsn` before overwriting `instance`;
  // the `dsn` label is used in the integration with the knowledge graph
  rule {
    source_labels = ["instance"]
    target_label  = "dsn"
  }
  rule {
    target_label = "instance"
    replacement  = "<INSTANCE_LABEL>"
  }
}

prometheus.scrape "database_observability_sqlserver_<DB_NAME>" {
  targets    = discovery.relabel.database_observability_sqlserver_<DB_NAME>.output
  forward_to = [prometheus.remote_write.metrics_service.receiver]
}
```

Replace the placeholders:

- `DB_NAME`: Database name Alloy uses in component identifiers (appears in component names and secret filenames).
- `AZURE_SUBSCRIPTION_ID`: Azure Subscription ID for your Azure SQL database.
- `AZURE_RESOURCE_GROUP`: Azure Resource Group that holds the logical server.
- `AZURE_SERVER_NAME`: Azure logical server name, for example `orders-db` for the host `orders-db.database.windows.net`.
- `INSTANCE_LABEL`: Value that sets the `instance` label on logs and metrics (optional).
- Secret file content example: `"sqlserver://<DB_O11Y_USER>:<DB_O11Y_PASSWORD>@<SERVER_FQDN>:<DB_PORT>?database=<DB_DATABASE>&encrypt=true"`.
  
  - `DB_O11Y_USER`: Contained user Alloy uses to connect (for example, `db-o11y`).
  - `DB_O11Y_PASSWORD`: Password for the database user.
  - `SERVER_FQDN`: Azure logical server fully qualified domain name (for example, `<SERVER_NAME>.database.windows.net`).
  - `DB_PORT`: Database port number (default: `1433`).
  - `DB_DATABASE`: The user database to monitor. It must have Query Store enabled and must not be `master`.

Because Azure SQL Database collects from only the single database in the DSN, give each database its own contained user and `database=` value. Repeat the blocks above for each database, or add one [`database_instance`](https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/database_observability/database_observability.sql_server/#database_instance) block per database in a single `database_observability.sql_server` component.

Find more about the options supported by the `database_observability.sql_server` component in the [reference](https://grafana.com/docs/grafana-cloud/send-data/alloy/reference/components/database_observability/database_observability.sql_server/) documentation.

The `cloud_provider` block integrates Database Observability with [Cloud Provider Observability](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/). To navigate between query performance and Azure infrastructure metrics, refer to [Preconfigured dashboards and alerts for Azure metrics](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/monitor-cloud-provider/azure/azure-alerts/#access-database-observability).

### Add Prometheus and Loki write configuration

Add the Prometheus remote write and Loki write configuration. From Grafana Cloud, open your stack to get the URLs and generate API tokens:

Alloy ![Copy code to clipboard](https://grafana.com/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
prometheus.remote_write "metrics_service" {
  endpoint {
    url = sys.env("GCLOUD_HOSTED_METRICS_URL")

    basic_auth {
      password = sys.env("GCLOUD_RW_API_KEY")
      username = sys.env("GCLOUD_HOSTED_METRICS_ID")
    }
  }
}

loki.write "grafana_cloud_loki" {
  endpoint {
    url = sys.env("GCLOUD_HOSTED_LOGS_URL")

    basic_auth {
      password = sys.env("GCLOUD_RW_API_KEY")
      username = sys.env("GCLOUD_HOSTED_LOGS_ID")
    }
  }
}
```

Replace the placeholders:

- `GCLOUD_HOSTED_METRICS_URL`: Your Grafana Cloud Prometheus remote write URL.
- `GCLOUD_HOSTED_METRICS_ID`: Your Grafana Cloud Prometheus instance ID (username).
- `GCLOUD_HOSTED_LOGS_URL`: Your Grafana Cloud Loki write URL.
- `GCLOUD_HOSTED_LOGS_ID`: Your Grafana Cloud Loki instance ID (username).
- `GCLOUD_RW_API_KEY`: Grafana Cloud API token with write permissions.

## Verify telemetry in Grafana Cloud

After Alloy starts, verify that Database Observability is receiving telemetry.

1. In Grafana Cloud, open **Database Observability**.
2. Go to **Configuration**.
3. Select **Telemetry status**.
4. Select your database instance.
5. Confirm that telemetry status checks pass.
6. Open **Queries overview** and confirm that query metrics appear.

After telemetry appears, the database instance should be visible and Queries overview should show query metrics. Additional data such as query samples, wait events, schema details, and explain plans becomes available as Alloy collects it and as the database engine supports it.

Telemetry can take a few minutes to appear. For detailed status checks, refer to [Verify telemetry status](https://grafana.com/docs/grafana-cloud/monitor-applications/database-observability/configure/verify-telemetry-status/).

## Troubleshoot first-run issues

If data doesn’t appear after setup:

- If the database instance doesn’t appear in Database Observability, check Alloy connectivity and labels.
- If telemetry status checks fail, use the Configuration page to identify the failed requirement.
- If schema details appear but query metrics don’t, confirm that Query Store is `READ_WRITE` on the database in the connection string and that the `db-o11y` user has `VIEW DATABASE STATE` there.
- If nothing is collected, confirm the DSN points at a user database and not `master`. Azure SQL Database can’t switch databases with `USE`, so a `master` connection collects nothing.
- If Alloy can’t connect to the database, check firewall rules, virtual network settings, DNS, and that encryption is enabled in the DSN.

For detailed guidance, refer to [Troubleshoot Alloy](https://grafana.com/docs/grafana-cloud/monitor-applications/database-observability/troubleshoot/alloy/) or [Troubleshoot SQL Server](https://grafana.com/docs/grafana-cloud/monitor-applications/database-observability/troubleshoot/sql_server/).

## Next steps

- [View query performance](https://grafana.com/docs/grafana-cloud/monitor-applications/database-observability/monitor/view-query-performance/)
- [Find your application’s queries](https://grafana.com/docs/grafana-cloud/monitor-applications/database-observability/monitor/find-application-queries/)
- [Link traces and queries](https://grafana.com/docs/grafana-cloud/monitor-applications/database-observability/monitor/link-traces/)
- [Analyze explain plans](https://grafana.com/docs/grafana-cloud/monitor-applications/database-observability/investigate/analyze-explain-plans/)
