Azure-SSIS runtime paying the Azure licence rate
A managed Azure-SSIS integration runtime with its licence set to LicenseIncluded, which Azure Hybrid Benefit would replace if the customer holds Software Assurance.
Why it happens
An Azure-SSIS integration runtime bills the SQL Server licence inside its node rate, so a licence type of LicenseIncluded means that charge is being paid to Azure on every node, every hour the runtime is started. Measured against the retail price list for East US, a Standard D4 v3 node costs 0.969 US dollars an hour with the licence included and 0.579 with the benefit applied, and the Enterprise edition of the same node costs 2.042 against the same 0.579, because the benefit removes the licence charge rather than discounting it. The rule reads a field that no other check in this product reads: managed instances and databases spell it properties.licenseType, SQL Server virtual machines spell it properties.sqlServerLicenseType with an entirely different set of values, and this one is nested inside typeProperties.ssisProperties, three levels deeper, using the managed instance values. A rule copied from either sibling would find nothing on every estate without failing. Only managed runtimes are reported, because a self-hosted runtime runs on the customer own machines, bills for data movement alone and carries no licence to switch. No saving is estimated. The node size and node count are both on this record and the meter names follow a clean pattern, but that mapping has not been checked against a running runtime, and a figure a customer acts on is not assembled from a pattern that merely looks right. Two things this cannot see are stated on every finding: whether the customer actually holds Software Assurance, which Azure does not record, and whether the subscription uses centrally managed Azure Hybrid Benefit, in which case the value on this record may not be what is billed.
Paste this into Resource Graph Explorer in the Azure portal.
resources
| where type =~ 'microsoft.datafactory/factories/integrationruntimes'
// Scope below matches CloudFinOpsPro policy DEFAULTS: exclusions.protectTag, environment.tagKeys,
// environment.allowedTagValues, and allowUntagged false so an untagged resource counts as production.
// If your policy.yaml differs, edit the three lines below or this will disagree with your own agent.
| where tolower(tostring(coalesce(tags['cfop:protect'], ''))) !in ('true', 'yes', '1')
| extend cfopEnv = tolower(trim(' ', tostring(coalesce(tags['Environment'], tags['environment'], tags['env'], ''))))
| where cfopEnv in ('dev', 'development', 'test', 'qa', 'sandbox', 'nonprod', 'non-prod', 'staging')
| extend runtimeKind = tostring(properties.type)
| extend ssisLicence = tostring(properties.typeProperties.ssisProperties.licenseType)
| extend edition = tostring(properties.typeProperties.ssisProperties.edition)
| extend nodeSize = tostring(properties.typeProperties.computeProperties.nodeSize)
| extend nodeCount = toint(properties.typeProperties.computeProperties.numberOfNodes)
| where runtimeKind =~ 'Managed'
| where ssisLicence =~ 'LicenseIncluded'
| project name, resourceGroup, location, ssisLicence, edition, nodeSize, nodeCount, environment = cfopEnvRead properties.typeProperties.ssisProperties.licenseType and NOT properties.licenseType. This is the fourth Azure Hybrid Benefit check and no two of them spell it the same way: a SQL managed instance and a SQL database carry licenseType directly on properties with BasePrice or LicenseIncluded, a SQL virtual machine carries sqlServerLicenseType with PAYG, AHUB or DR, and an integration runtime carries the managed instance VALUES at a path three levels deeper. A query copied from either sibling returns nothing on every estate, silently. LicenseIncluded is the one paying Azure for the licence; BasePrice is the benefit already applied, which is the opposite way round to how the two names read. The runtime kind filter is an allowlist of Managed, because a SelfHosted runtime runs on your own machines, bills for data movement alone and has no licence to switch, so a runtime kind Azure adds later is silent rather than wrongly reported. IMPORTANT, and the reason this query may return nothing even where a runtime exists: the generated Azure Resource Graph supported-types reference lists microsoft.DataFactory/factories with no child entry, so it is not established that Resource Graph indexes integration runtimes at all. If this returns zero rows on an estate that owns an Azure-SSIS runtime, that is the answer to a question we have open rather than a clean estate. See issue 386.
Applies to microsoft.datafactory/factories/integrationruntimesWhat the agent does about it
A managed Azure-SSIS integration runtime with its licence set to LicenseIncluded, which Azure Hybrid Benefit would replace if the customer holds Software Assurance.
It will not fix this one
It finds it and tells you what to change. The change itself is yours to make, because it is not one the agent should make on your behalf.
Related checks
HDInsight worker nodes without autoscale
A Spark, Hadoop or Interactive Query cluster whose worker role has no autoscale configured, so it pays for peak worker capacity every hour of every day.
SQL Managed Instance without Azure Hybrid Benefit
A SQL Managed Instance paying the licence-included rate, which a customer holding SQL Server licences with Software Assurance can lower without downtime.
Serverless SQL database with auto-pause switched off and nothing using it
A General Purpose serverless SQL database with auto-pause disabled that had no sessions and no CPU at any point in the window, so it billed its minimum compute floor around the clock for doing nothing.