Wednesday, April 1, 2026

Azure Is Selling You Half a Core at Full SQL Server Price

The Azure migration pitch is convincing. Lower overhead, no hardware refresh cycles, pay for what you use. Management loves it. The CFO approved the budget. The project kicked off. And then — somewhere between the on-prem decommission and the first Azure invoice — somebody notices the SQL Server licensing line is larger than expected. Quite a bit larger.

This is not a billing error. It is a VM selection problem — and it is very easy to walk straight into if nobody flags it during the planning phase.

The Short Version

Azure VMs are sized in vCPUs — virtual CPUs. On most Azure VM series, one vCPU is one hyper-threaded logical core (hyper-threading is the common name for SMT — Simultaneous Multithreading), not one physical core. A physical core with hyper-threading enabled exposes two logical cores to the operating system. SQL Server sees both logical cores. SQL Server licensing counts both logical cores. But under any real CPU load, those two logical cores share the physical core's execution resources. You are paying for two licenses to run on what is, functionally, one core's worth of throughput.

On-premises, this distinction rarely bites you. VMware will preferentially schedule a VM's vCPUs across different physical cores rather than packing two threads onto the same core. You tend to get close to physical core performance per vCPU. Azure does not offer that guarantee. In a multi-tenant cloud environment, your VM gets the vCPUs you paid for — logical cores, fairly distributed — and that's it.

Joe Obbish documented this thoroughly last week over at Darling Data. The research is solid. Go read it. What I want to do here is translate what it means for you — and for your customers — before the migration truck shows up.

What the Numbers Actually Look Like

This is not a theoretical concern. The cost difference between VM families, expressed as effective SQL Server licensing cost per physical core, is significant enough to change a project budget.

VM Series SMT Monthly Cost License / Physical Core
E16bds v5 Enabled $5,892.56 $547.50
F16ams v7 Disabled $5,962.64 $259.52

The monthly sticker price is nearly identical but the effective licensing cost per physical core is more than double. The workload that fits on a 16-physical-core on-prem box may need 32 vCPUs on a hyper-threaded Azure VM to deliver equal throughput — which means 32 licensed cores instead of 16. On SQL Server Enterprise Edition, that difference is not a rounding error. It is a budget conversation you do not want to have after the migration is done.

A commenter on Joe's post said it plainly: 'This seems intentional, honestly.' Whether it is or not, it doesn't change the math. What matters is that you know about it before your customer's first invoice, not after.

Why Nobody Catches This in the Planning Phase

The Azure sizing conversation usually goes like this: 'You're on a 16-core on-prem VM, so let's look at 16-vCPU Azure VMs.' The vCPU count matches. The memory looks right. The pricing seems reasonable. The migration plan gets approved. What the conversation missed was a question about whether those 16 vCPUs represent 16 physical cores or 8 physical cores with hyper-threading, and what that means for both performance and licensing.

The Azure documentation I've seen does not surface this loudly. The VM series pages describe vCPU counts, memory, and storage. The specific marketing language about 'full physical cores' only appears on the series that don't use SMT — ie., the ones where the distinction is a selling point. On the series that do use hyper-threading, there is no equivalent language flagging it. You have to know to look.

There is also a natural assumption carried over from on-prem: hyper-threading doesn't affect SQL Server licensing on physical hardware. Microsoft's own licensing guide says so. That rule applies to physical servers. Azure VMs are a different licensing surface, and the assumption does not transfer.

Joe Obbish calls it a licensing trap. That is exactly the right word for it — because it only catches you if you don't see it coming.

What to Check While Planning Your Customer's Move to Azure

First, know exactly what you're moving. How many physical cores is the current SQL Server licensed for, and what is the actual CPU usage pattern? A lightly loaded instance at 10% CPU is a different migration conversation than one at 60–70% usage.

-- Current core count and SQL Server edition
SELECT
    cpu_count                          AS logical_cpus,
    hyperthread_ratio,
    cpu_count / hyperthread_ratio      AS physical_cores,
    SERVERPROPERTY('Edition')          AS edition
FROM sys.dm_os_sys_info;

If hyperthread_ratio is 2 and cpu_count is 16, you have 8 physical cores with hyper-threading enabled. That 8-physical-core workload moved to a hyper-threaded Azure VM will need 16 vCPUs to match throughput — which is 16 licensed cores. If your current licensing is based on 8 physical cores, this has just become a licensing change, not just a migration.

Second, check average and peak CPU utilization. Moving an instance that rarely exceeds 20% CPU is much less sensitive to the hyper-threading distinction than one running hot. High utilization is exactly when hyper-threaded logical cores start delivering only 50% of physical core performance, and exactly when the licensing math hurts most.

-- Recent CPU utilization from the ring buffer (last ~256 minutes)
SELECT TOP 30
    DATEADD(ms, -1 * (ts.ms_ticks - rb.[timestamp]),  GETDATE()) AS sample_time,
    rec.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') AS sql_cpu_pct,
    100 - rec.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int')   AS total_cpu_pct
FROM sys.dm_os_ring_buffers rb
CROSS JOIN sys.dm_os_sys_info ts
CROSS APPLY (SELECT CONVERT(xml, rb.record)) x(rec)
WHERE rb.ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR'
ORDER BY rb.[timestamp] DESC;

Third, before you commit to a VM series, review the docs and verify one thing: does this VM give me a full physical core per vCPU, or a hyper-threaded logical core? The answer determines how many SQL Server licenses you will need. Most Azure VM series are hyper-threaded — one physical core exposes two vCPUs, and SQL Server licenses both of them at full price. A small number of series ship without hyper-threading, where one vCPU genuinely equals one physical core. Microsoft only calls this out when it is true. The Famsv7 series explicitly says 'vCPU is mapped to a full physical core.' The Ebdsv5 says no such thing — because it doesn't apply. If the documentation does not say it, assume you are buying logical cores and license accordingly.

The Escape Routes, and Their Honest Trade-offs

There is no clean answer here. Each option has a cost:

Option The Catch
Choose an SMT-disabled VM series Limited families; ie., no local temp storage on Famsv7
Disable hyper-threading inside the VM Preview feature; doesn't help on Microsoft-licensed VMs, BYOL only
Use constrained vCPU sizes No guarantee of physical core scaling
Right-size a lightly loaded instance No help for heavy OLTP

The takeaway is not 'Don't go to Azure.' It's 'Know what you're buying before you commit'. A 16-vCPU hyper-threaded Azure VM is a fundamentally different licensing and performance proposition than a 16-physical-core on-prem server, and the migration plan should account for that difference explicitly.

Where This Shows Up in a Health Check

When I do a SQL Server health check on an instance being considered for cloud migration, the CPU utilization profile and current licensing baseline are part of the conversation. An instance running at 65% CPU on 8 physical cores does not migrate cleanly to a hyper-threaded 16-vCPU VM and come out with the same performance and license cost. The performance will likely be lower. The license cost will likely be higher. That's a finding, not a footnote.

If you are in the middle of an Azure migration conversation right now, it's worth a quick look at the target VM spec before the project sign off. The pricing difference between a hyper-threaded VM and a physical-core VM at the same vCPU count can easily exceed $200 per physical core per month on SQL Server Enterprise. At scale, and over a three-year Azure commitment, that math becomes real very fast.

Get the VM selection right before you move. It is a much easier conversation than explaining the bill afterward.

More to Read:

Hyper-threading on Azure VMs is a SQL Licensing Trap — Joe Obbish, Darling Data
Famsv7-series Azure VMs (no SMT) — Microsoft Learn
Constrained vCPU sizes for Azure VMs — Microsoft Learn
SQL Server Health Check — sqlfingers.com