DEV Community

Mohammad Shoeb
Mohammad Shoeb

Posted on

Azure Isn't Expensive β€” Your Code Is: 10 Proven Patterns That Cut Costs Fast

πŸ”₯ Why This Blog Matters
❌ A company I worked with once spent $7,400 in a single month…
Just because an Azure Function was triggered around 8 million times β€” by stale messages in a forgotten queue.
The devs didn’t even know it was still active.

πŸ’‘ You don’t need cheaper pricing tiers.
You need smarter code.

This post is your developer-first playbook.
I’ll show you 10 real code patterns that:

Slash compute, storage, and telemetry waste
Are used inside Microsoft (Azure SDKs, Copilot infra, and durable workloads)
Can be implemented within a couple of weeks
Not a medium member? you can read this blog here.

πŸ‘» Pattern 0: Cost Ghosts β€” What’s Billing You Silently
β€œYou can’t optimize what you don’t measure.” β€” Azure Advisor Team

πŸ‘Ž Common Mistake:
Ignoring silent costs from idle VMs, orphaned App Services, or chatty logs.

βœ… Fix:
Start with diagnostics:

Azure Cost Analysis β†’ by tag or service
Application Insights β†’ filter high-traffic routes
Azure Workbooks β†’ cost-by-operation
Azure Advisor β†’ underutilized resources
πŸ’‘ Quick Win: Tag every resource by team + feature. Unused ones will light up.

🧠 Pattern 1: Queue-First, Not Compute-First
πŸ‘Ž Common Mistake:
Triggering Functions or APIs directly per event β€” even when it could wait.

βœ… Fix:
Use Storage Queues, Service Bus, or Event Hubs to buffer and batch.

API β†’ Queue β†’ Azure Function (batch trigger)
β€œQueues are cheaper than compute. Push work downstream.” β€” Azure Arch Center

πŸ’‘ Quick Win: Ingest telemetry β†’ Event Hub β†’ Storage Queue β†’ Batch Function

πŸ“‰ Potential Savings: 30–60% reduction in over-scaled compute

⏳ Pattern 2: Time-to-Live Everything
πŸ‘Ž Common Mistake:
Cosmos DB, queues, and logs live forever. You keep paying for ghost data.

βœ… Fix:
Use TTL aggressively:

Cosmos DB: defaultTimeToLive
Service Bus: TimeToLive
Blobs: lifecycle policies
Durable Functions: auto-purge history
β€œUse TTL to enforce data lifecycle and reduce cost.” β€” Cosmos TTL Docs

πŸ’‘ Quick Win: Set Service Bus TTL = 48 hours. Cosmos = 7 days.

πŸ“‰ Potential Savings: 10–25% on storage & telemetry

πŸ“ˆ Pattern 3: Cap Concurrency β€” Don’t Over-AutoScale
πŸ‘Ž Common Mistake:
Relying on autoscaling alone leads to bill spikes under load.

βœ… Fix:
Apply hard caps:

Azure Function β†’ maxConcurrentRequests
Web APIs β†’ SemaphoreSlim, ParallelOptions
Polly β†’ BulkheadPolicy
β€œConcurrency limits prevent downstream exhaustion and surprise bills.” β€” Functions Scale Docs

πŸ’‘ Quick Win: Limit queue-triggered Functions to 5 concurrent instances.

πŸ“‰ Potential Savings: 30–50% compute reduction in spikes

🧾 Pattern 4: Structured Logging + Sampling
πŸ‘Ž Common Mistake:
Logging every HTTP response at Information. Every. Single. Time.

βœ… Fix:
Use:

Structured logs:
_logger.LogInformation("Order {Id} processed at {Time}", id, DateTime.UtcNow);
Application Insights sampling
Log filters in host.json
β€œUse sampling to reduce ingestion, not insight.” β€” App Insights Docs

πŸ’‘ Quick Win: Use AdaptiveSamplingTelemetryProcessor. It auto-throttles verbosity.

πŸ“‰ Potential Savings: 40–70% on App Insights ingestion cost

⏱️ Pattern 5: Use Durable Timers Instead of Waiting
πŸ‘Ž Common Mistake:
Using Task.Delay or polling loops β€” which bills you per second.

βœ… Fix:
Use context.CreateTimer(...) in Durable Functions:

await context.CreateTimer(DateTime.UtcNow.AddMinutes(15), CancellationToken.None);
β€œDurable timers pause without active billing.” β€” Durable Functions Docs

πŸ’‘ Quick Win: Replace Thread.Sleep with CreateTimer in approval workflows.

πŸ“‰ Potential Savings: 50–90% on wait-heavy Functions

πŸ“¦ Pattern 6: Blob Tiering Isn’t Optional
πŸ‘Ž Common Mistake:
Leaving all blobs in Hot Tier β€” even audit logs and backups.

βœ… Fix:
Use Lifecycle Management to move:

Hot β†’ Cool β†’ Archive β†’ Delete
β€œArchive storage is up to 80% cheaper than Hot.” β€” Azure Storage Pricing

πŸ’‘ Quick Win: Set lifecycle policy:
30 days β†’ Cool
90 days β†’ Archive
180 days β†’ Delete

πŸ“‰ Potential Savings: 50–80% on storage cost

🧲 Pattern 7: Trigger Filters Save You Real Money
πŸ‘Ž Common Mistake:
Function triggered by every Event Grid event β€” even irrelevant ones.

βœ… Fix:
Use:

Event Grid filters (eventType, subject)
Service Bus SQL filters
Cosmos DB Change Feed filters
β€œFilter events at the source to reduce compute.” β€” Event Grid Filters

πŸ’‘ Quick Win: Trigger only when eventType == "InvoiceCreated"

πŸ“‰ Potential Savings: 20–40% reduction in Function invocations

πŸ” Pattern 8: Resilient Outbound Calls: Retry + Bulkhead
πŸ‘Ž Common Mistake:
Retrying failed APIs immediately β†’ creates a retry storm.
Or worse β€” calling external APIs at 1000 RPS when they handle 50.

βœ… Fix:
Use:

new BlobClientOptions
{
Retry = {
MaxRetries = 5,
Mode = RetryMode.Exponential,
Delay = TimeSpan.FromSeconds(2)
}
}
And cap concurrency:

await semaphore.WaitAsync();
// API Call
semaphore.Release();
β€œSmart retries and bulkheads reduce downstream throttling and cost.” β€” Azure SDK + Cloud Patterns

πŸ’‘ Quick Win: Use Polly + SemaphoreSlim for any 3rd-party API call.

πŸ“‰ Potential Savings: Up to 50% reduction in failed/duplicated requests

πŸ“Š Pattern 9: Track Cost per Route, Not Just Monthly Spend
πŸ‘Ž Common Mistake:
Reviewing cost by month or service β€” not by API route or feature.

βœ… Fix:
Use App Insights operation_Name
Correlate with Azure Cost Exports
Build Workbooks to analyze cost per endpoint
β€œTags + correlation = true FinOps insight.” β€” Azure FinOps Docs

πŸ’‘ Quick Win: Tag by project, owner, feature. Then sort cost by those.

πŸ“‰ Potential Savings: Visibility = control = smarter decisions

🎁 Bonus Pattern 10: Stop Paying for Premium SKUs You Don’t Need
πŸ‘Ž Common Mistake:
Using P1 Redis, Standard App Service, or AKS with 3-node pools for tiny workloads.

βœ… Fix:
Audit your SKU usage:

Redis: Use Basic unless you’re clustering
App Service: Move idle apps to Free or Consumption
AKS: Scale to 0 or move to Azure Container Apps
β€œPremium doesn’t mean better. Just pricier.” β€” Azure Advisor

πŸ’‘ Quick Win: Downgrade unused Redis cache from P1 to Basic.

πŸ“‰ Potential Savings: $500–$1500/month depending on SKUs

βœ… Start Here: Apply These 3 Today
Add TTL to Cosmos + Service Bus
Cap Function concurrency to 5
Enable sampling in App Insights
πŸ” Watch your Azure bill dip within 48 hours.

🧠 Final Thought
Smart code isn’t just faster β€” it’s cheaper. And it starts today.

πŸ’¬ Found a pattern you’re using already β€” or one that surprised you?
Drop it in the comments or share this with a teammate burning Azure cash.

Top comments (0)