Azure Synapse Analytics Errors, Connection, Throttling, and Query Performance Fixes

Microsoft Fix Intermediate 14 min read Official Docs Grounded Updated April 20, 2026

Why This Is Happening

You submitted a query to your Azure Synapse dedicated SQL pool. It ran fine last week. Today it's been sitting there for twenty minutes, spinning, and the only thing your monitoring dashboard is telling you is nothing useful. Or worse, you got back a cryptic error like 110806; A distributed query failed and you're staring at it wondering where to even start.

I've seen this exact scenario on dozens of enterprise deployments. Azure Synapse Analytics errors aren't like ordinary SQL errors. The engine is massively parallel, distributed across compute nodes, and has its own internal query lifecycle, compilation, resource allocation, execution, and data movement, any of which can break down independently. A single slow query isn't always a slow query. Sometimes it's a blocked compilation. Sometimes it's a resource class mismatch. Sometimes tempdb on a single compute node quietly filled up and the error message gives you almost no hint that's what happened.

Here's what makes Azure Synapse dedicated SQL pool troubleshooting genuinely hard: the error messages surface at the top layer, but the root cause lives several layers down. Error 8632 ("Internal error: An expression services limit has been reached") sounds like a system bug but it's actually telling you your query is too complex for the optimizer. Error 110806 covers a wide family of distributed query failures, connectivity between compute nodes, resource pressure, tempdb exhaustion, and DMS operation failures all share that same error prefix. Microsoft's error messages are accurate, but they're not generous with context.

The other thing I see constantly: teams hit Azure Synapse query performance issues because their workload has outgrown the resource class assigned to the user running the queries. As your data grows and joins get more complex, memory grants that used to be sufficient start falling short. The query doesn't fail immediately, it just waits, and waits, and the monitoring graph shows a session blocked on resource allocation while everyone wonders if the service is down.

There's also a class of Azure Synapse connection errors and throttling problems that spike when many queries get submitted simultaneously. Compilation concurrency blocks, where a large wave of queries queues up waiting just to begin compiling, are rare but nasty when they hit. They look like everything froze at once.

The good news: every one of these failure modes has a diagnostic path and a fix. Browse all Microsoft fix guides →

The Quick Fix, Try This First

Before you go deep into DMV queries and execution plans, try the single action that resolves the largest proportion of Azure Synapse dedicated SQL pool issues in production environments: pause and resume the pool.

This sounds too simple, but it's what Microsoft's own documentation recommends as the first mitigation for several distinct error classes, including the "Database cannot be opened due to inaccessible files or insufficient memory or disk space" error and the MSDTC unavailability error ("The service that manages global transactions isn't functioning appropriately"). A pause/resume cycle resets the service state, flushes transient resource pressure, and re-establishes node connectivity without data loss.

Here's exactly how to do it:

  1. Open the Azure Portal at portal.azure.com.
  2. Navigate to your Azure Synapse workspace, then select SQL pools from the left menu.
  3. Click the name of your dedicated SQL pool.
  4. On the pool overview page, click the Pause button in the top action bar. Confirm when prompted.
  5. Wait for the pool status to show Paused, this typically takes 2–5 minutes.
  6. Click Resume and wait for status to return to Online.

After resuming, retry the failing query. If it was a transient Azure Synapse connection error or a service health blip, it will work now. If the error returns, that's actually useful, it means the root cause is structural, and you need to go deeper using the diagnostic steps below.

One important nuance: if you're seeing 110806 errors related to tempdb exhaustion specifically, a pause/resume alone won't permanently fix it. It clears the symptom but the underlying query or workload pattern will fill tempdb again. You need to address the workload alongside the restart.

Pro Tip
When you resume the pool, immediately run SELECT * FROM sys.dm_pdw_exec_requests WHERE status = 'Running' before submitting any user workload. If you see lingering sessions from before the pause, they're ghost requests, note their request_id values and kill them before they block fresh compilation queues.
1
Identify the Exact Failure Phase Using DMV Queries

The first thing you need to establish is where in the query lifecycle the failure is occurring. Azure Synapse Analytics query performance problems break down into two broad phases: Compilation and Execution. You can't fix a compilation block with an execution-phase mitigation, so getting this right first saves you hours of chasing the wrong fix.

Run this against your dedicated SQL pool, substituting the actual session ID of the problematic query for @session_id. You can find active session IDs in the Azure Portal under Monitoring → SQL requests, or by querying sys.dm_pdw_exec_sessions.

-- Find your request_id first
SELECT session_id, request_id, status, submit_time, command
FROM sys.dm_pdw_exec_requests
WHERE status NOT IN ('Completed', 'Failed', 'Cancelled')
ORDER BY submit_time DESC;

Once you have the request_id (it looks like QID12345), plug it into the step-level query:

DECLARE @QID VARCHAR(16) = 'QID12345', @ShowActiveOnly BIT = 1;

SELECT step_index AS [StepIndex],
       'Execution' AS [Phase],
       operation_type + ' (' + location_type + ')' AS [Description],
       start_time AS [StartTime],
       end_time AS [EndTime],
       total_elapsed_time / 1000.0 AS [Duration],
       [status] AS [Status],
       CASE WHEN estimated_rows > -1 THEN estimated_rows END AS [EstimatedRowCount],
       CASE WHEN row_count > -1 THEN row_count END AS [ActualRowCount],
       command AS [TSQL]
FROM sys.dm_pdw_request_steps
WHERE request_id = @QID
  AND [status] = CASE @ShowActiveOnly WHEN 1 THEN 'Running' ELSE [status] END
ORDER BY step_index;

If rows come back, your query is in the Execution phase and you can see exactly which step is running. If no rows come back but the query shows as "Running" in Step 1, you're in a Compilation phase block, a fundamentally different problem. Note what the Description column says in either case; that value maps directly to the mitigation path.

2
Diagnose Compilation Blocks, Concurrency and Resource Allocation

If your query is stuck in the compilation phase, there are two distinct causes to rule out: compilation concurrency blocks and resource allocation blocks. They look similar from outside but need different fixes.

Run this to check whether a compilation block exists and who's causing it:

DECLARE @session_id INT = <your_session_id>, @QID VARCHAR(16) = '<request_id>';

SELECT waiting.session_id,
       waiting.request_id,
       'Compilation' AS [Phase],
       'Blocked by ' + blocking.session_id + ':' + blocking.request_id
         + ' when requesting ' + waiting.type
         + ' on ' + QUOTENAME(waiting.object_type) + waiting.object_name AS [Description],
       waiting.request_time AS [StartTime],
       DATEDIFF(ms, waiting.request_time, GETDATE()) / 1000.0 AS [Duration]
FROM sys.dm_pdw_waits AS waiting
INNER JOIN sys.dm_pdw_waits AS blocking
  ON waiting.object_type = blocking.object_type
  AND waiting.object_name = blocking.object_name
INNER JOIN sys.dm_pdw_exec_requests AS blocking_exec_request
  ON blocking.request_id = blocking_exec_request.request_id
WHERE waiting.session_id = @session_id
  AND waiting.state = 'Queued'
  AND blocking.state = 'Granted'
  AND waiting.type != 'Shared';

If the Description column says "Blocked by [session]:[request] when requesting...", you have a compilation concurrency block. This happens when a large volume of queries floods the system simultaneously. The fix is straightforward but sometimes uncomfortable: reduce concurrent query submissions. You may need to implement a queue at the application layer or adjust how batch jobs submit work.

If instead the block description mentions resource allocation, that means your query is waiting for a memory grant based on the resource class assigned to the executing user. Check which resource class that user is in and compare it against the workload's actual memory requirements. The fix is either bumping the user's resource class, waiting for blocking sessions to complete, or, when urgency demands it, killing the blocking session. Make that call carefully in production.

3
Drill Into Distribution-Level Execution With Step Details

Once you've identified a specific step that's running slowly using the query from Step 1, you can go one layer deeper and see exactly what's happening at each distribution. This is where you find out if one distribution is running hot while others finished, the classic data skew signature, or whether a specific wait type is strangling throughput across all distributions.

DECLARE @QID VARCHAR(16) = '<request_id>', @StepIndex INT = <StepIndex>, @ShowActiveOnly BIT = 0;

WITH dists AS (
    SELECT request_id, step_index, 'sys.dm_pdw_sql_requests' AS source_dmv,
           distribution_id, pdw_node_id, spid, 'NativeSQL' AS [type],
           [status], start_time, end_time, total_elapsed_time, row_count
    FROM sys.dm_pdw_sql_requests
    WHERE request_id = @QID AND step_index = @StepIndex

    UNION ALL

    SELECT request_id, step_index, 'sys.dm_pdw_dms_workers' AS source_dmv,
           distribution_id, pdw_node_id, sql_spid AS spid, [type],
           [status], start_time, end_time, total_elapsed_time, rows_processed AS row_count
    FROM sys.dm_pdw_dms_workers
    WHERE request_id = @QID AND step_index = @StepIndex
)
SELECT sr.step_index, sr.distribution_id, sr.pdw_node_id, sr.spid,
       sr.type, sr.status, sr.start_time, sr.end_time,
       sr.total_elapsed_time, sr.row_count,
       owt.wait_type, owt.wait_time
FROM dists sr
LEFT JOIN sys.dm_pdw_nodes_exec_requests owt
  ON sr.pdw_node_id = owt.pdw_node_id
  AND sr.spid = owt.session_id
ORDER BY distribution_id;

Set @ShowActiveOnly to 0 to get the full picture across all distributions, not just currently active ones. Look at two things in the result set: the total_elapsed_time spread across distributions (huge variance = skew problem) and the wait_type column. The wait type tells you exactly what resource the slowest distribution is contending for, IO, memory, locks, which directly points to the mitigation. A skewed distribution usually means your hash distribution column is a poor choice for that table's query patterns.

4
Fix Common Error Codes, 8632, 110806, and CCI Health

Let's walk through the error codes you're most likely to encounter running Azure Synapse Analytics queries in production, and what to actually do about each one.

Error 8632, Expression services limit reached: This means your query is too complex for the optimizer to handle in a single pass. The error message says "simplify your query" which feels like unhelpful advice, but it's literally the fix. Break the query into multiple CTEs or temp table stages. Long chains of subqueries and deeply nested joins are the most common trigger. Rewriting to ANSI-92 style explicit JOINs (not WHERE-clause join conditions) also helps significantly, the optimizer handles them more efficiently.

Error 110806, Distributed query failed (tempdb full): When the error includes "Could not allocate space for object in database 'tempdb'", at least one compute node's tempdb partition has filled up. Immediate fix: pause and resume the pool. But then you need to understand what filled it. Large sorts, hash joins on non-distributed columns, and queries that generate massive intermediate result sets are the usual culprits. Increasing the user's resource class gives the operation more memory, which reduces how much spills to tempdb.

Error 110806, DMS operation failure (Error ID): This specific variant often means the Data Movement Service ran out of resources during inter-node data shuffling. Bump the user's resource class to match the workload size. Also check whether sys.dm_pdw_permanent_table_mappings can replace any references you have to sys.pdw_table_mappings, the permanent view is meaningfully faster for metadata retrieval.

Unhealthy CCIs, deleted/open row percentages: If your clustered columnstore indexes have a high percentage of deleted or open rows, the optimizer can't produce accurate estimates. Run delta store health checks and consider a scheduled ALTER INDEX REBUILD or REORGANIZE on the affected CCIs. This one sneaks up on teams because it degrades gradually rather than breaking suddenly.

-- Check CCI health across all tables
SELECT OBJECT_NAME(object_id) AS table_name,
       index_id,
       delta_store_hobt_id,
       state_desc,
       total_rows,
       deleted_rows,
       size_in_bytes
FROM sys.dm_db_column_store_row_group_physical_stats
WHERE state_desc IN ('OPEN', 'TOMBSTONE')
ORDER BY total_rows DESC;
5
Address Auto-Create Statistics Delays and Timeouts

One Azure Synapse query performance issue that catches people by surprise: when you run a query and it completes, but it was preceded by several CREATE STATISTICS statements that ran automatically. These auto-created statistics are usually a good thing, they help the optimizer. But there are two failure modes worth knowing.

Statistics created unexpectedly, causing query delay: If you see CREATE STATISTICS statements firing immediately after slow query submissions, you're experiencing a delay from auto-create statistics. The statistics job kicks in because the optimizer detected it needed fresh stats to plan the query, and that extra work added latency. This is mostly benign but worth monitoring. Pre-creating statistics on your most-queried columns eliminates this overhead.

Statistics creation failing after 5 minutes: This is a harder problem. The auto-statistics job times out before it can finish, leaving the optimizer without good estimates, which cascades into bad query plans. The fix is to create those statistics manually and explicitly:

-- Manually create statistics on high-impact columns
CREATE STATISTICS stats_customer_id ON dbo.orders(customer_id);
CREATE STATISTICS stats_order_date ON dbo.orders(order_date);
CREATE STATISTICS stats_product_id ON dbo.order_items(product_id);

Once you've manually created stats on your key join and filter columns, the auto-stats process has less work to do and timeout failures drop dramatically. Also review the distribution policy on your tables, if a table is distributed on a column that doesn't match your most common join predicate, you're generating unnecessary data movement at every query and the query optimizer is working with poor cardinality estimates from the start.

To audit your table distribution policies alongside index types, run this diagnostic:

SELECT t.object_id,
       SCHEMA_NAME(t.schema_id) AS [schema_name],
       t.name AS table_name,
       tdp.distribution_policy_desc,
       c.name AS hash_distribution_column_name
FROM sys.tables t
JOIN sys.pdw_table_distribution_properties tdp
  ON t.object_id = tdp.object_id
LEFT JOIN sys.pdw_column_distribution_properties cdp
  ON t.object_id = cdp.object_id AND cdp.distribution_ordinal = 1
LEFT JOIN sys.columns c
  ON cdp.object_id = c.object_id AND cdp.column_id = c.column_id
ORDER BY t.name;

If you find large fact tables distributed on columns that aren't your primary join keys, that's a redesign conversation, but it's the kind of structural fix that makes every subsequent query faster, not just the one you're debugging today.

Advanced Troubleshooting

I know this is frustrating, especially when the surface-level fixes don't move the needle and you're dealing with enterprise-scale workloads where every minute of degraded performance is visible to the business. Here are the deeper diagnostic and architectural paths that resolve the hardest Azure Synapse Analytics connection errors and performance problems.

Workload Management and Resource Class Tuning

Azure Synapse dedicated SQL pools control query memory grants through resource classes and workload groups. When queries queue on resource allocation, the core question is whether the current resource class is appropriate for the actual memory demand. Larger resource classes grant more memory per query but reduce concurrency, you can't have both unlimited memory and unlimited concurrency simultaneously.

Check your current workload group assignments:

SELECT r.login_name,
       r.request_id,
       r.status,
       r.resource_class,
       r.importance,
       r.total_elapsed_time
FROM sys.dm_pdw_exec_requests r
JOIN sys.dm_pdw_exec_sessions s ON r.session_id = s.session_id
WHERE r.status = 'Running'
ORDER BY r.total_elapsed_time DESC;

If critical queries are assigned to smallrc but they're joining multi-billion-row fact tables, move those users to mediumrc or largerc and test the trade-off against concurrency. For mixed workloads, workload classifiers in the workload group system let you route specific queries to dedicated pools of resources without affecting everything else.

DROP TABLE and TRUNCATE TABLE Performance

Long-running DROP TABLE or TRUNCATE TABLE statements blocking other queries is a specific pattern the documentation calls out. These statements aren't instantaneous on large tables in a distributed environment, they need to coordinate across all distributions. If your ETL patterns involve frequent drops and recreates of large tables, consider switching to TRUNCATE TABLE over DROP TABLE where possible, since truncate is a metadata-only operation on empty tables. Better yet, use partition switching for staging patterns, it's dramatically faster.

Query Hints for Complex Join-Filter Logic

When compilation phase slowness is caused by a complex query with many joins, especially any that use WHERE-clause join conditions instead of explicit JOIN syntax, you can apply query hints to override the optimizer's default behavior:

SELECT /* your query here */
OPTION(FORCE ORDER, USE HINT ('FORCE_LEGACY_CARDINALITY_ESTIMATION'));

FORCE ORDER tells the optimizer to process joins in the exact order you wrote them, which short-circuits the expensive join reordering search. FORCE_LEGACY_CARDINALITY_ESTIMATION switches to the older cardinality estimator, which performs better in some scenarios with complex predicates. These are not permanent fixes, they're diagnostic tools that can confirm whether the optimizer is the bottleneck while you refactor the query properly.

FORMAT() Function Performance

One specific, easy-to-miss Azure Synapse query performance drain: heavy use of the FORMAT() function. It runs through the SQL CLR layer and has significant overhead at scale. If you have reports or transformations that call FORMAT() thousands of times per query, replace them with CONVERT() with an explicit style code:

-- Instead of this:
SELECT FORMAT(order_date, 'yyyy-MM-dd') AS formatted_date FROM orders;

-- Do this:
SELECT CONVERT(VARCHAR(10), order_date, 120) AS formatted_date FROM orders;

On large datasets this swap alone can cut execution time by 30–50% on the affected steps.

When to Call Microsoft Support

Escalate to Microsoft Support if: (1) you're seeing the MSDTC error ("The service that manages global transactions isn't functioning appropriately") recurring after multiple pause/resume cycles, that's a service-layer issue Microsoft needs to investigate on their infrastructure side; (2) the 110806 connectivity errors between compute nodes are increasing in frequency over time rather than being isolated incidents; (3) you've increased resource class and SLO and are still hitting memory allocation failures for queries that should fit within the new grant. These patterns indicate something outside your configuration control.

Prevention & Best Practices

Once you've resolved the immediate Azure Synapse Analytics error, the goal is making sure the same thing doesn't quietly creep back in over the next few weeks. The most common pattern I see: teams fix a performance issue, don't change anything structurally, and three months later when the data volume has grown 40% they're debugging the same symptoms again.

The biggest structural investment you can make is getting your table distribution design right. Hash-distributed tables on the right column eliminate an enormous amount of data movement, which is the single biggest driver of execution-phase slowness in Synapse. The right distribution column is the one that appears most often in your JOIN predicates. For tables that are joined infrequently, replicated distribution avoids movement entirely. Run the distribution audit query from Step 5 regularly as your schema evolves.

Keep your clustered columnstore indexes healthy. CCIs with high percentages of deleted rows or open delta store segments degrade both storage efficiency and query performance progressively. Build CCI maintenance into your regular ETL schedule, not just index rebuilds, but also monitoring the delta store row group states so you catch degradation before it affects users.

Workload management deserves dedicated attention before you scale up concurrency. As more users and more workloads hit the pool, the default resource class assignments that worked for 10 concurrent queries start causing queuing problems at 50. Define workload classifiers that route different query types to appropriate resource pools. Give your ETL processes higher importance classification so they don't get starved during peak user activity.

Statistics maintenance is often neglected until query plans go visibly wrong. Auto-create statistics helps but it has limits, especially on skewed data distributions. Create statistics manually on your highest-traffic join and filter columns, and update them on a schedule that reflects how quickly your data changes.

Quick Wins
  • Replace FORMAT() function calls with CONVERT(value, style) in all reporting queries, the performance difference at scale is immediate and measurable.
  • Switch all join syntax to ANSI-92 explicit JOIN style if you have any legacy queries using WHERE-clause join conditions, the optimizer handles them materially better.
  • Schedule a weekly CCI health check using sys.dm_db_column_store_row_group_physical_stats and auto-trigger rebuilds when delta store open row percentage exceeds 20%.
  • Replace any references to sys.pdw_table_mappings in monitoring scripts with sys.pdw_permanent_table_mappings, it's significantly faster for metadata retrieval and prevents the 110806 metadata timeout error.

Frequently Asked Questions

Why does my Azure Synapse query show "Running" in monitoring but have no step information?

This means your query is stuck in the compilation phase rather than execution. When sys.dm_pdw_exec_requests shows status "Running" but sys.dm_pdw_request_steps returns no rows for that request ID, compilation hasn't finished. The most common causes are a compilation concurrency block (too many queries submitted simultaneously) or a resource allocation block (waiting for a memory grant based on resource class). Run the compilation block diagnostic query from Step 2 to identify which blocking session you're waiting on. Don't confuse this with a slow query, it never started executing yet.

What does "110806; A distributed query failed" actually mean and why does it cover so many different errors?

Error 110806 is a catch-all prefix for failures during distributed query execution, it fires when something goes wrong at the infrastructure layer connecting control nodes to compute nodes. The actual failure could be compute node connectivity loss, resource pressure causing the operation to abort, tempdb exhaustion on a specific distribution, or a DMS (Data Movement Service) operation running out of memory. You have to read the full error text after the 110806 prefix to determine which category you're in, because each one has a different mitigation. Tempdb exhaustion says "could not allocate space for object in database 'tempdb'." Connectivity issues say something about connections being unavailable. Treat the 110806 prefix as "something failed inside the distributed layer" and then parse the detail.

How do I know if my Azure Synapse performance problem is caused by data skew?

Run the distribution-level detail query from Step 3 and set @ShowActiveOnly to 0 so you see all distributions, not just active ones. Then look at the total_elapsed_time column across all distribution IDs. If one or two distributions show dramatically higher elapsed times while others finished quickly, say, 45 seconds versus 2 seconds, you have skew. The slow distribution got a disproportionate share of the data because the hash distribution column has low cardinality or a heavily repeated value. The fix is typically changing the distribution column on that table to one with better cardinality relative to your actual query patterns. You can also check row counts per distribution using DBCC PDW_SHOWSPACEUSED('schema.table_name').

My Azure Synapse dedicated SQL pool keeps hitting "insufficient disk space" errors, what's filling up?

The error "Could not allocate a new page for database 'Distribution_nn' because of insufficient disk space in filegroup 'PRIMARY'" points to rowstore indexes or heaps exceeding available space in at least one distribution. This is almost always a combination of two things: table skew causing one distribution to hold far more data than others, and the fact that rowstore tables (heap or traditional B-tree indexed) don't compress as efficiently as columnstore. First, check for skew on the tables involved. Second, evaluate whether those tables should be converted to clustered columnstore indexes for better compression. Third, check your max database size configuration in the pool settings and increase it if you're genuinely running out of capacity across all distributions.

Should I kill the blocking session that's preventing my query from getting resources?

It depends on what that blocking session is doing and how long it's been running. If it's a legitimate, long-running ETL load that started before your query submitted, killing it means re-running that load, potentially losing significant progress. Microsoft's own documentation lists "kill the blocking session" as an option but pairs it with "evaluate if it's preferable" for a reason. If the blocking session is a runaway query that got stuck, check how long it's been running and whether it's actually making progress via the step detail query, killing it is more defensible. In production, the safer first move is always to wait or to escalate resource class so your query can compete rather than forcing a disruption to whatever is currently running.

How often should I update statistics on Azure Synapse dedicated SQL pool tables?

There's no single right answer, but a useful rule of thumb is: update statistics whenever a table has had more than 10–20% of its rows modified since the last statistics update. For tables with daily ETL loads, that often means daily. For slowly changing dimension tables, weekly or even monthly may be sufficient. The auto-create statistics feature handles creation but doesn't reliably handle updates, you need to either use UPDATE STATISTICS schema.table on a schedule or script per-column updates for your highest-traffic join columns. The cost of stale statistics is bad query plans that look correct from outside but run 10x slower than they should because the optimizer made wrong cardinality assumptions at plan time.

Related Microsoft Fix Guides

H
Sai Kiran Pandrala
Our team includes certified Microsoft engineers, Azure architects, and system administrators with 10+ years of enterprise IT experience. Every guide is written from hands-on troubleshooting, not guesswork. We test every fix before publishing.