SQL Server Performance Tuning

Why Your App Got Slow After Migrating SQL Server to Azure

Updated
13 min read
Written by
Mark Varnas
Reviewed by
Saulius Baskevicius
TLDR: After a SQL Server Azure migration, a slow app is almost never a database problem. The bottleneck is usually outside SQL Server — network latency, VPN or ExpressRoute routing, firewall inspection, DNS, or an app pulling large datasets across a cloud connection. Tuning the database wastes time. 

The fix is benchmarking on-prem first and testing your actual application against Azure before cutover.

When an app gets slow after you migrate SQL Server to Azure, everyone points at the database. The DBA gets the ticket. Tuning begins. Usually, it accomplishes nothing.

We went through this recently with a client. They moved from on-premises to Azure.

They were running two SQL Server instances on a single Azure VM — their application vendor had recommended this setup. The application itself was a legacy desktop client connecting from on-premises workstations through a VPN tunnel to the cloud-hosted database.

Performance dropped immediately. Users were frustrated.

Their ask: “Something is wrong with the database. Please tune it.”

So we did. We right-sized the compute, increased storage performance, tuned IOPS and latency, put tempdb on the fastest tier available, and applied every standard database best practice that typically makes a measurable difference. After each change, we asked end users: “Better?”

Every time: “No. Still slow.”

From the database side, everything looked fine. Queries were fast. Resource waits were low. The metrics told one story. The users told another.

So we stopped tuning and sat with the users to watch the app live.

The app was crawling. The database was not breaking a sweat.

The database was never the problem.

Why the Database Always Gets Blamed

DBAs are the default blame acceptor in most IT environments. Something goes slow? Blame the database first, tune the database first, waste time on the database first.

This reflex made more sense on-premises, where the application and database were close together on a local network and the bottleneck often was query performance or resource contention. In the cloud, especially during or after a migration, that assumption breaks down fast.

When you move SQL Server to Azure, the database itself typically behaves well. Modern Azure VM tiers with Premium SSD or Ultra Disk can match or exceed on-premises storage performance. Compute is configurable. SQL Server tuning best practices are the same in any environment. If you run a well-configured instance, the database is rarely where your performance problem lives.

What changes dramatically is everything between the application and the database.

Where the Slowness Actually Comes From

In the migration we described, the database was healthy the entire time. What we found when we looked outside SQL Server was a combination of factors that collectively killed application performance.

Network path and latency. On-premises, your application server and SQL Server probably shared the same LAN. Round-trip time between app and database was measured in microseconds. In Azure, that path changes. If your application is still on-premises while your database moved to the cloud, every query now crosses a WAN link. Even with a fast connection, that latency adds up fast when an application makes hundreds of small round-trips per page load.

VPN or ExpressRoute routing. The route traffic actually takes to reach Azure is not always the direct one. VPN configurations, forced tunneling, and ExpressRoute routing policies can add hops and latency that never existed on-premises. A network that performs well under normal traffic can add significant overhead when SQL traffic starts crossing it continuously.

Security inspection. Firewalls, deep packet inspection, and antivirus scanning can intercept and delay SQL Server traffic in ways that are hard to detect without specifically looking for them. This is especially common in environments where security teams applied on-premises security policies to Azure traffic without adjusting them for cloud workloads.

Azure VM throughput ceilings. A less-obvious trap: every Azure VM size has a maximum throughput cap at the VM level, independent of the storage you attach. You can provision disks with 20,000 IOPS, but if your VM size caps throughput at 6,400 IOPS, you will hit that ceiling regardless. Many teams size their storage correctly and miss this entirely. Always verify VM-level IOPS and bandwidth limits against your expected workload before migration.

DNS resolution. Slow or misconfigured DNS can delay connection establishment to SQL Server. In hybrid environments where DNS is resolved on-premises before traffic goes to Azure, a single misconfigured lookup can add latency to every connection.

Application behavior. Some applications are written to pull large datasets from SQL Server and filter or render them client-side. On a local network this is tolerable. Across a cloud connection, pulling 100,000 rows where you need 500 is a real problem. SQL Server executes the query quickly. The transfer time kills you.

The interesting part of our client case is that when we watched the database during the slow app session, wait stats were clean. CPU was low. IO was not stressed. There was no blocking. By every database metric, performance was normal. The app just happened to be on the wrong side of a slow pipe.

Bottleneck What It Looks Like How to Identify It
Network latency / VPN overhead App slow, database metrics healthy Run network trace, compare response times from different locations
Firewall inspection Intermittent slowdowns, packet delays Check firewall logs for packet inspection delays
Antivirus scanning Random spikes, I/O delays Check if AV is scanning SQL data files or temp directories
Azure VM throughput ceiling Consistent slow I/O despite SSD storage Monitor Azure disk metrics for throttling against VM-level limits
Application pulling large datasets Slow loads, healthy query execution times Profile query row counts vs what the app actually uses
DNS resolution Slow connection establishment Compare connection times before and after migration

How to Troubleshoot This

If you are seeing slowness after migration and the database metrics look healthy, stop tuning the database. Start here instead.

Watch the application and the database at the same time. Open a session with your users and observe the app behavior while monitoring SQL Server with sys.dm_exec_requests and sys.dm_os_wait_stats. If the database shows no significant waits while the app is visibly slow, your problem is outside SQL Server.

Measure network latency specifically. Run a simple connection test from your application server to your Azure SQL Server or Azure VM. If round-trip time is higher than a few milliseconds, that is your starting point. On-premises SQL traffic typically runs under 1ms. Anything over 5ms will be noticeable in chatty applications.

Check your network path. Run a traceroute from the application server to the Azure endpoint and count the hops. Look for unexpected routing. Confirm whether ExpressRoute is actually being used for your SQL traffic or whether it is going over a public internet path.

Review security inspection rules. Ask your security team whether firewall or AV policies are intercepting SQL Server traffic. This is a more common issue than most people expect, and it is almost never volunteered as a possibility until you specifically ask.

Look at the application’s query patterns. If the application is pulling large result sets and filtering them outside SQL Server, that becomes an architectural problem after migration. Fixing it requires application changes, not database tuning.

What to Do Before You Migrate SQL Server To Azure

The far better position is to find these issues before you cut over, not after. Most post-migration performance problems are discoverable in advance if you test properly.

Benchmark your on-premises baseline first. Before migration, capture end-to-end application response times, query durations for your most-used queries, and network latency between app and database. These numbers become your reference point. You cannot know whether Azure performance is acceptable if you do not know what on-premises performance looked like.

Set up a test Azure environment and connect your actual application to it. This is the step most teams skip. They run database benchmarks against Azure, confirm the database performs well, and consider the test done. The right test is connecting your real application to your Azure SQL Server and running realistic user workflows. That is where network path issues, VPN routing problems, and application behavior issues actually surface.

This is the same logic behind distributed workload replay testing, which we have used to catch Azure sizing and performance issues before clients commit to a configuration.

Testing with real workloads, not synthetic benchmarks, is what catches real problems.

Map your network path in advance. Know how traffic will route from your application to Azure before migration. If you are using ExpressRoute, confirm that SQL traffic will use it. If you are using VPN, understand the forced tunneling configuration. Know what your expected round-trip latency will be under normal and peak load.

Identify chatty application patterns. Before migration, review your application’s top SQL queries by execution count. A query that runs 10,000 times per minute is far more sensitive to latency than one that runs 10 times per day. If your application has high-frequency, low-row-count queries, latency between app and database matters more than raw query performance.

Plan security inspection explicitly. Work with your security team before migration to understand how SQL traffic will be handled in Azure. If firewall or AV policies will inspect SQL traffic, test that configuration before cutover and measure its impact.

The general principle: it is far easier to isolate bottlenecks in a test environment than after you are live.

Post-migration, users are affected, pressure is high, and the instinct is to blame the most visible component. Doing this work before migration means you can isolate issues without that pressure.

Frequently Asked Questions

Why does app performance drop after migrating SQL Server to Azure even when the database is healthy?

The most common reason is increased latency between the application and the database. On-premises, app and database are typically on the same LAN with sub-millisecond round trips. After migration, if the application is still on-premises or in a different network zone, that latency increases. For applications that make many small database calls per user action, even a few milliseconds of added latency per call compounds into visible slowness. The database executes queries just as fast. The time is lost in transit.

How do I tell whether the database or the network is causing the slowness?

Monitor SQL Server during a slow session. Check sys.dm_exec_requests for active wait types and sys.dm_os_wait_stats for cumulative waits. If the database shows low CPU, few IO waits, and no significant blocking while the application is visibly slow, the bottleneck is outside SQL Server. Combine this with a network latency measurement from the application server to the database server. If round-trip time is measurably higher than your on-premises baseline, start there.

What is the right network connection for SQL Server in Azure?

For production workloads, ExpressRoute is the standard recommendation over public internet or VPN. It provides a dedicated, private connection between your on-premises network and Azure with more predictable latency. That said, ExpressRoute needs to be configured correctly for SQL traffic to actually use it. Confirm your routing configuration rather than assuming it.

Should we benchmark before migrating SQL Server to Azure?

Yes. Capture end-to-end application response times, query durations for high-frequency queries, and network latency before migration. Use those numbers as your baseline for evaluating Azure performance. Without a baseline, you cannot distinguish a real performance problem from a configuration gap, and you have no objective reference for what “good” looks like in your environment.

What Azure VM limits affect SQL Server performance?

Each Azure VM size has a maximum throughput cap for both IOPS and bandwidth, independent of the storage you attach. A VM with a 6,400 IOPS cap will throttle even if your disk supports 20,000 IOPS. Always check the VM-level limits in Microsoft’s documentation before selecting your configuration.

Can antivirus software slow down SQL Server on Azure?

Yes. If antivirus is configured to scan SQL Server data files (.mdf, .ndf, .ldf), backup files, or tempdb, it causes file locks and I/O delays that directly impact query performance. Microsoft recommends excluding SQL Server data directories, backup directories, and the tempdb path from antivirus real-time scanning.
Compare database-side query execution time with what the application reports. If a query executes in 50 milliseconds at the database but the application shows 3 seconds of wait time, the gap is in the network, application, or middleware layer — not SQL Server. Tools like Wireshark or Azure Network Watcher can help pinpoint where latency is introduced.

Should I run two SQL Server instances on one Azure VM?

In most cases, no. Both instances compete for the same CPU, memory, and disk I/O. Unless there is a strong architectural reason such as vendor-mandated isolation, consolidating to a single instance gives you better resource visibility and is easier to manage.

What is ephemeral storage in Azure, and should I use it for SQL Server?

Ephemeral storage (local temporary disk) is the fastest available storage on Azure VMs because it sits physically on the host machine. It works well for tempdb. For persistent databases, use Premium SSD or Ultra Disk with appropriate IOPS provisioning. Be aware that ephemeral storage is lost if the VM is deallocated.

When It Actually is the Database

Not every post-migration slowdown has an external cause. If your Azure VM is under-provisioned — wrong size, wrong storage tier, tempdb misconfigured — database-side symptoms will show up clearly in the wait stats.

Check these before assuming the problem is external:

High CPU or IO waits in sys.dm_os_wait_stats. CXPACKET waits pointing to parallelism misconfiguration on the new VM size. PAGEIOLATCH waits indicating storage pressure. Blocking chains visible in sys.dm_exec_requests that weren’t present on-premises.

If those are present, start with the database. If the database metrics are clean while the app is visibly slow, the bottleneck is elsewhere.

The sequence matters more than anything else: confirm the database is actually under stress before spending time fixing it.

Bottom Line

The client moved to Azure. The app got slow. We tuned the database because that was the ask. Everything we changed was correct — right-sized compute, faster storage, tempdb on the best tier available. None of it moved the needle.

The database was never under stress.

An hour watching the app with users revealed what days of database tuning missed. Network path, VPN configuration, security inspection — problems that look identical to a database performance issue until you actually check the wait stats and find nothing there.

Fast migrations don’t happen by accident. They happen because someone benchmarked the baseline, tested the real application against Azure before cutover, and looked at the full path — not just the database.

Speak with a SQL Expert

In just 30 minutes, we will show you how we can eliminate your SQL Server headaches and provide 
operational peace of mind

Article by
Mark Varnas
Founder | CEO | SQL Veteran
Hey, I'm Mark, one of the guys behind Red9. I make a living performance tuning SQL Servers and making them more stable.

Discover More

SQL Server Health Check SQL Server Migrations & Upgrades SQL Server Performance Tuning SQL Server Security SQL Server Tips

Discover what clients are saying about Red9

Red9 has incredible expertise both in SQL migration and performance tuning.

The biggest benefit has been performance gains and tuning associated with migrating to AWS and a newer version of SQL Server with Always On clustering. Red9 was integral to this process. The deep knowledge of MSSQL and combined experience of Red9 have been a huge asset during a difficult migration. Red9 found inefficient indexes and performance bottlenecks that improved latency by over 400%.

Rich Staats 5 stars
Rich Staats
Cloud Engineer
MetalToad

Always willing to go an extra mile

Working with Red9 DBAs has been a pleasure. They are great team players and have an expert knowledge of SQL Server database administration. And are always willing to go the extra mile to get the project done.
5 stars
Evelyn A.
Sr. Database Administrator

Boosts server health and efficiency for enhanced customer satisfaction

Since adding Red9 to the reporting and DataWarehousing team, Red9 has done a good job coming up to speed on our environments and helping ensure we continue to meet our customer's needs. Red9 has taken ownership of our servers ensuring they remain healthy by monitoring and tuning inefficient queries.
5 stars
Andrew F.
Datawarehousing Manager
See more testimonials