DEV Community

Cover image for I Broke Production on Azure. Here's What I Learned (And Why I Still Love It)
Ibne sabid saikat
Ibne sabid saikat

Posted on

I Broke Production on Azure. Here's What I Learned (And Why I Still Love It)

Let me be real with you.
The first time I deployed something on Azure, I was confident. Like, dangerously confident. Clicked through the portal like I knew exactly what I was doing, hit deploy, and watched my app go live.
Then I got the bill.
Not catastrophic. But enough to make me stare at the cost breakdown at 1 AM thinking, "What is an Azure App Service Plan and why did I pick P3v3?"
That was two years ago. Since then, Azure has become the cloud I actually understand — not just use. And I want to share some of the stuff nobody tells you in the official docs.

First: Stop Treating Azure Like AWS With a Different Logo
I see this constantly. Developers coming from AWS try to 1:1 map everything. EC2 → Virtual Machine. S3 → Blob Storage. Lambda → Azure Functions.
And yeah, those mappings roughly work. But Azure has a fundamentally different philosophy in some areas, and if you fight it instead of learning it, you're going to have a bad time.
The biggest mindset shift: Azure is deeply integrated with the Microsoft ecosystem. That's not a limitation — it's a superpower if you use it right.
Your company uses Active Directory? Entra ID (formerly Azure AD) just... works. You're building on .NET? App Services has first-class support that feels native. You need enterprise governance across multiple subscriptions? Azure Policy and Management Groups are genuinely excellent.
Once I stopped porting my AWS mental model and started learning Azure on its own terms, everything clicked.

The Thing Nobody Explains: Resource Groups Are Not Just Folders
When you're new to Azure, Resource Groups look like folders. You put stuff in them. You organize things.
Wrong.
Resource Groups are the unit of lifecycle management. Everything inside a Resource Group shares the same lifecycle. When you delete the group, everything goes. When you apply a policy or lock, it cascades down.
This changes how you design your architecture.
Don't do this:
ResourceGroup-Production/
├── web-app
├── database

├── storage
└── monitoring
Think more like this:
rg-myapp-prod-westeurope/
└── (everything for this app, this environment, this region)

rg-myapp-staging-westeurope/
└── (staging stack, completely isolated)

rg-shared-infra-prod/
└── (networking, monitoring, stuff that spans apps)
The naming convention matters too. Azure has a recommended pattern and honestly, follow it. {resource-type}-{workload}-{environment}-{region}-{instance} looks verbose until you have 200 resources and need to find something at 3 AM.

Azure CLI > Portal (Fight Me)
The portal is beautiful. It's also where you learn things once. The CLI is where you actually work.
bash# Log in
az login

Set your subscription (do this first, always)

az account set --subscription "your-subscription-id"

Create a resource group

az group create \
--name rg-myapp-prod \
--location eastus

Deploy an App Service (this is actually fast)

az webapp up \
--name my-cool-app \
--resource-group rg-myapp-prod \
--runtime "NODE:20-lts" \
--sku B1
That last command (az webapp up) is genuinely magic. It creates the App Service Plan, the App Service, deploys your code, and gives you a URL. One command.
The Portal is great for exploring — understanding what options exist, what something looks like configured. The CLI is great for doing — scripting, automating, being consistent across environments.
Use both. But learn the CLI properly.

Azure Functions: Where I Actually Fell In Love
I was skeptical of serverless for a long time. Seemed like a solution looking for a problem.
Then I had to build an image processing pipeline. User uploads an image, we resize it to 5 different dimensions, generate thumbnails, and store them. Classic stuff.
With Azure Functions + Blob Triggers, this was almost embarrassingly simple:
pythonimport azure.functions as func
from PIL import Image
import io

app = func.FunctionApp()

@app.blob_trigger(
arg_name="myblob",
path="uploads/{name}",
connection="AzureWebJobsStorage"
)
def process_image(myblob: func.InputStream, name: str):
# Blob trigger fires the moment someone uploads
image = Image.open(io.BytesIO(myblob.read()))

sizes = [(150, 150), (400, 400), (800, 800)]
for width, height in sizes:
    resized = image.copy()
    resized.thumbnail((width, height))
    # Save to output binding...

print(f"Processed {name} — {myblob.length} bytes")
Enter fullscreen mode Exit fullscreen mode

The Blob Trigger handles all the event plumbing. You just write the logic. Scale to zero when idle, scales up automatically when your viral post sends 10,000 images at once.
Cold start is still a thing. For latency-sensitive stuff, use Premium plan or keep-alive pings. But for async workloads? Functions are my go-to.

Managed Identity: Use It. Always.
This one is non-negotiable for me now.
Early on I did the thing everyone does: put connection strings in environment variables. Database URL, storage account key, all of it. Checked into appsettings.json once (yes, I know).
Managed Identity eliminates credential management entirely. Your App Service or Function App gets an identity in Entra ID. You grant that identity permissions to your resources. Done. No keys, no rotation, no accidental commits.
bash# Enable system-assigned managed identity on your app
az webapp identity assign \
--name my-cool-app \
--resource-group rg-myapp-prod

Grant it read access to a Key Vault

az keyvault set-policy \
--name my-keyvault \
--object-id {identity-object-id} \
--secret-permissions get list
In your code, it just works:
pythonfrom azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient

credential = DefaultAzureCredential()
client = SecretClient(vault_url="https://my-keyvault.vault.azure.net/", credential=credential)
secret = client.get_secret("my-database-password")
DefaultAzureCredential automatically uses Managed Identity in production and your local credentials in development. Zero config changes between environments.

The Cost Management Thing (Learn This Before You Need It)
Azure Cost Management is genuinely good. Use it proactively, not reactively.
Set up budget alerts. Seriously. Five minutes of setup, and you'll get an email before you have a bad month.
bashaz consumption budget create \
--budget-name monthly-budget \
--amount 100 \
--time-grain Monthly \
--start-date 2025-01-01 \
--end-date 2025-12-31 \
--resource-group rg-myapp-prod \
--notification-threshold 80 \
--notification-email your@email.com
The things that will surprise you with cost:

App Service Plans: You pay for the plan, not the apps. Put multiple apps on one plan (in non-production).
Public IP addresses: They cost money now. Don't create them unless you need them.
Storage transactions: Blob storage looks cheap until you have millions of tiny reads.
Bandwidth egress: Data leaving Azure costs money. Design to minimize it.

Azure Advisor will give you cost recommendations. It's not always right, but check it weekly. It found a zombie VM I'd forgotten about once. That was a good day.

What I Wish I'd Known Earlier
Azure Monitor + Application Insights is a complete observability stack. Don't reach for Datadog immediately. Try Application Insights first. It has distributed tracing, custom metrics, live metrics stream, and alerting. It's excellent and you're probably already paying for it.
Bicep over ARM templates. If you're doing Infrastructure as Code on Azure, Bicep is the answer. ARM templates are XML-level painful. Bicep is clean, has great VS Code support, and compiles to ARM anyway.
Azure DevOps and GitHub Actions both work great with Azure. I personally prefer GitHub Actions now, and the Azure-specific actions (azure/login, azure/webapps-deploy) are well-maintained.
The free tier is actually useful. Static Web Apps free tier is genuinely good for side projects. Azure Functions Consumption plan gives you 1 million free executions per month. You can run a serious project for free.

Where I Am Now
After two years, Azure is my primary cloud. Not because it's perfect — it isn't. The portal is sometimes confusing, some services feel incomplete, and the documentation can be inconsistent.
But the depth of the ecosystem, the enterprise-grade identity story, and the way everything integrates when you're all-in on the Microsoft stack is genuinely impressive. The developer experience has improved dramatically in the last two years.
And honestly? Breaking things and fixing them is how you actually learn. I'm still breaking things. Just more deliberately now.

If you're building on Azure and hit something confusing, drop it in the comments. I've probably made that same mistake.
Also doing a YouTube series on Azure for developers — link in bio if you want to see the actual hands-on stuff.

Top comments (0)