Skip to main content

Azure Cost Optimization for .NET Applications: Save 40% on Your Cloud Bill

April 11, 2026 5 min read

It's entirely possible to cut an Azure bill by 30-40% without degrading performance. The changes aren't revolutionary — right-sizing, commitment discounts, intelligent autoscaling, and fixing surprisingly expensive oversights. Let's walk through the techniques that actually move the needle, with practical commands and code examples you can apply today.

Right-Sizing: The Low-Hanging Fruit

Azure Advisor already tells you which VMs and App Service plans are over-provisioned — most teams just never look:

az advisor recommendation list \
  --category Cost \
  --query "[?shortDescription.problem=='Right-size or shutdown underutilized virtual machines'].{
    VM: resourceMetadata.resourceId,
    Savings: extendedProperties.savingsAmount,
    CurrentSKU: extendedProperties.currentSku,
    RecommendedSKU: extendedProperties.targetSku
  }" --output table

The biggest wins come from App Service plans — teams often run a single API on a P3v3 when a P1v3 handles the load comfortably. Check CPU and memory utilization over a two-week period before right-sizing. For memory-constrained plans, consider switching to workstation GC:

<PropertyGroup>
  <ServerGarbageCollection>false</ServerGarbageCollection>
</PropertyGroup>

Workstation GC uses less memory at the cost of more frequent (but shorter) GC pauses. For APIs with low to moderate traffic, this can let you drop to a smaller App Service tier without performance impact.

Reserved Instances and Savings Plans

For 24/7 workloads, pay-as-you-go is leaving money on the table:

Resource Pay-as-you-go 1-Year Reserved 3-Year Reserved
D4s_v5 VM ~$280/mo ~$175/mo (37% off) ~$112/mo (60% off)
SQL Database S3 ~$150/mo ~$100/mo (33% off) ~$75/mo (50% off)

Prices approximate, vary by region. Check Azure Pricing Calculator for current rates.

Azure Savings Plans apply discounts across compute services regardless of region or size — often a better fit than reserved instances for teams that frequently resize. Start with 1-year commitments for production workloads and extend to 3-year when you're confident in the resource requirements.

Application Insights: The Hidden Cost Driver

App Insights can quietly become one of the biggest cost drivers. A single application generating 50M telemetry items per month can cost more than the compute running it. Fix with adaptive sampling:

builder.Services.AddApplicationInsightsTelemetry();
builder.Services.Configure<TelemetryConfiguration>(config =>
{
    var processorBuilder = config.DefaultTelemetrySink.TelemetryProcessorChainBuilder;
    processorBuilder.UseAdaptiveSampling(maxTelemetryItemsPerSecond: 5, excludedTypes: "Event");
    processorBuilder.Build();
});

// Filter health check noise
builder.Services.AddApplicationInsightsTelemetryProcessor<HealthCheckFilter>();

Kubernetes probes hitting every pod every 10 seconds generate millions of request items monthly. Here's a custom telemetry processor to filter them out:

public class HealthCheckFilter : ITelemetryProcessor
{
    private readonly ITelemetryProcessor _next;

    public HealthCheckFilter(ITelemetryProcessor next) => _next = next;

    public void Process(ITelemetry item)
    {
        if (item is RequestTelemetry request &&
            (request.Url.AbsolutePath.Contains("/health") ||
             request.Url.AbsolutePath.Contains("/alive")))
            return; // Drop health check telemetry

        _next.Process(item);
    }
}

Set daily ingestion caps in the Azure portal as a safety net — an unexpected traffic spike or logging bug can generate massive telemetry volumes overnight.

Storage Tier Optimization

Implement lifecycle management — most blob data is rarely accessed after 30 days:

{
  "rules": [{
    "name": "move-to-cool-after-30-days",
    "enabled": true,
    "type": "Lifecycle",
    "definition": {
      "filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["logs/", "exports/"] },
      "actions": {
        "baseBlob": {
          "tierToCool": { "daysAfterModificationGreaterThan": 30 },
          "tierToArchive": { "daysAfterModificationGreaterThan": 90 },
          "delete": { "daysAfterModificationGreaterThan": 365 }
        }
      }
    }
  }]
}

Hot → Cool saves ~52%; Hot → Archive saves ~91% for 1TB of storage. Apply lifecycle policies to any container storing logs, exports, backups, or historical data.

Autoscaling Done Right

Scale down at night and use meaningful metrics:

az monitor autoscale create \
  --resource-group my-rg --name my-scale-settings \
  --resource "/subscriptions/{sub}/.../serverFarms/my-plan" \
  --min-count 2 --max-count 10 --count 2

az monitor autoscale rule create \
  --resource-group my-rg --autoscale-name my-scale-settings \
  --condition "CpuPercentage > 70 avg 10m" --scale out 2

az monitor autoscale rule create \
  --resource-group my-rg --autoscale-name my-scale-settings \
  --condition "CpuPercentage < 30 avg 10m" --scale in 1

For AKS, combine HPA with cluster autoscaler and KEDA for event-driven scaling based on queue depth. The cluster autoscaler adds nodes when pods can't be scheduled and removes them when utilization drops — preventing idle node costs that accumulate quickly in multi-node clusters.

Dev/Test Resource Scheduling

Non-production environments running 24/7 waste significant budget. Automate shutdown schedules for dev and test resources:

# Tag resources for automated management
az resource tag --ids /subscriptions/{sub}/resourceGroups/dev-rg \
  --tags Environment=Development AutoShutdown=true Schedule="M-F 08:00-18:00"

Use Azure Automation runbooks or Logic Apps to start and stop resources on schedule. A typical dev environment running only during business hours costs ~65% less than running continuously. For teams with multiple dev/staging environments, this can represent the single largest cost savings opportunity.

Key Takeaways

  1. Right-size everything — Azure Advisor alone typically identifies significant savings.
  2. Commit to reservations — 1-year saves ~30-40%, 3-year saves ~50-60% for always-on workloads.
  3. Tame Application Insights — sampling, health check filters, and daily caps.
  4. Tier your storage — lifecycle policies for anything older than 30 days.
  5. Autoscale with intention — scale down at night, use meaningful metrics.
  6. Kill dev/test resources on schedule — shut down non-production environments outside business hours.

Start with quick wins (right-sizing, reservations, dev/test schedules), then work through Application Insights tuning, storage tiering, and autoscaling. Track progress in Azure Cost Management.

References

  1. Azure Cost Management documentation — Tools for monitoring, analyzing, and optimizing Azure costs
  2. Azure Advisor cost recommendations — Automated right-sizing and cost optimization recommendations
  3. Azure Savings Plans — Flexible compute discounts across Azure services
  4. Application Insights sampling — Reducing telemetry volume and costs with adaptive sampling
  5. Azure Blob Storage lifecycle management — Automating tier transitions and deletion policies

Comments