Back to blog
Backend Systemsbeginner

Azure for Developers — The Services Every .NET Developer Needs to Know

A practical introduction to Azure for developers. App Service, Azure SQL, Storage, Key Vault, Application Insights — the core services you'll use on every project.

Asma HafeezApril 17, 20268 min read
azureclouddotnetapp-servicedevops
Share:𝕏

Azure for Developers — The Services You'll Actually Use

Most Azure tutorials start with a confusing 300-service catalogue. This one doesn't. We'll cover the eight services you'll use on almost every .NET project, why they exist, and how to get something running today.

By the end of this lesson you'll have a mental model of Azure that makes every other Azure tutorial easier to follow.


Why Azure?

Azure is Microsoft's cloud platform. For .NET developers it's the natural home because:

  • Deep integration with Visual Studio, VS Code, and GitHub Actions
  • Managed services for SQL Server, Redis, Service Bus — things you already know
  • .NET runtime support is first-class, not an afterthought
  • Enterprise adoption is massive — knowing Azure makes you employable

The core concept is simple: instead of managing servers, you deploy to managed services that scale, back up, and self-heal automatically.


The Eight Services You Need to Know

1. Azure App Service — Host Your Web App

App Service is where your ASP.NET Core API lives. You deploy your code; Azure runs it on managed infrastructure.

You push code → App Service pulls it → Your API is live at yourapp.azurewebsites.net

Key features:

  • Auto-scaling (scale out to multiple instances under load)
  • Deployment slots (deploy to staging, then swap to production with zero downtime)
  • Built-in SSL/TLS
  • Custom domains

Deploy from VS Code:

Bash
# Install Azure CLI
winget install Microsoft.AzureCLI

# Login
az login

# Create resource group
az group create --name MyRG --location norwayeast

# Create App Service plan (B1 = cheapest paid tier)
az appservice plan create --name MyPlan --resource-group MyRG --sku B1 --is-linux

# Create web app for .NET 8
az webapp create \
  --name my-api-app \
  --resource-group MyRG \
  --plan MyPlan \
  --runtime "DOTNET|8.0"

# Deploy your published output
az webapp deploy \
  --resource-group MyRG \
  --name my-api-app \
  --src-path ./publish.zip \
  --type zip

2. Azure SQL Database — Managed SQL Server

Azure SQL is SQL Server in the cloud. Zero schema migration needed if you're coming from SQL Server. Full T-SQL support, EF Core works identically.

Connection from .NET:

C#
// appsettings.json
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=myserver.database.windows.net;Database=mydb;Authentication=Active Directory Default;"
  }
}

// Program.cs
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

Pricing tip: Use Serverless tier for dev/test — you pay only when the database is actually executing queries. It auto-pauses after 1 hour of inactivity.


3. Azure Blob Storage — Store Files, Images, Backups

Blob Storage is Azure's object storage — for files, images, PDFs, backups, anything that's not relational data.

Container → Blob
(like Folder → File)

Upload a file from .NET:

Bash
dotnet add package Azure.Storage.Blobs
C#
using Azure.Storage.Blobs;

public class StorageService
{
    private readonly BlobServiceClient _blobClient;

    public StorageService(IConfiguration config)
    {
        _blobClient = new BlobServiceClient(
            config.GetConnectionString("AzureStorage"));
    }

    public async Task<string> UploadFileAsync(
        string containerName, string fileName, Stream content)
    {
        var container = _blobClient.GetBlobContainerClient(containerName);
        await container.CreateIfNotExistsAsync(PublicAccessType.Blob);

        var blob = container.GetBlobClient(fileName);
        await blob.UploadAsync(content, overwrite: true);

        return blob.Uri.ToString();
    }

    public async Task<Stream> DownloadFileAsync(
        string containerName, string fileName)
    {
        var container = _blobClient.GetBlobContainerClient(containerName);
        var blob = container.GetBlobClient(fileName);
        var response = await blob.DownloadAsync();
        return response.Value.Content;
    }
}

4. Azure Key Vault — Store Secrets Safely

Never store secrets in appsettings.json or environment variables. Azure Key Vault is the right place.

Key Vault stores: connection strings, API keys, certificates, TLS certs
App Service reads them: at startup, with no secrets in your codebase

Access Key Vault from .NET:

Bash
dotnet add package Azure.Extensions.AspNetCore.Configuration.Secrets
dotnet add package Azure.Identity
C#
// Program.cs — load all Key Vault secrets as configuration
using Azure.Identity;

var builder = WebApplication.CreateBuilder(args);

var keyVaultUrl = builder.Configuration["KeyVault:Url"];
if (!string.IsNullOrEmpty(keyVaultUrl))
{
    builder.Configuration.AddAzureKeyVault(
        new Uri(keyVaultUrl),
        new DefaultAzureCredential() // uses Managed Identity in production
    );
}

DefaultAzureCredential tries multiple auth methods in order: Managed Identity, Visual Studio, Azure CLI, etc. In production (App Service with Managed Identity), it just works with zero credentials in code.


5. Application Insights — Observability for Free

Application Insights is Azure's monitoring service. Add it to any .NET app and instantly get:

  • Request/response tracing
  • Dependency tracking (SQL queries, HTTP calls, Redis)
  • Exception capturing with full stack traces
  • Performance dashboards
  • Custom metrics and events
Bash
dotnet add package Microsoft.ApplicationInsights.AspNetCore
C#
// Program.cs
builder.Services.AddApplicationInsightsTelemetry(options =>
{
    options.ConnectionString = builder.Configuration["ApplicationInsights:ConnectionString"];
});

That's it. No other code needed. Every HTTP request is automatically traced. Every SQL query duration is logged. Every unhandled exception is captured.

Custom events and metrics:

C#
public class OrderService
{
    private readonly TelemetryClient _telemetry;

    public OrderService(TelemetryClient telemetry)
        => _telemetry = telemetry;

    public async Task<Order> CreateOrderAsync(CreateOrderRequest request)
    {
        var order = /* create order */;

        // Track a custom event
        _telemetry.TrackEvent("OrderCreated", new Dictionary<string, string>
        {
            ["CustomerId"] = order.CustomerId,
            ["Total"] = order.Total.ToString("F2")
        });

        // Track a custom metric
        _telemetry.TrackMetric("OrderTotal", (double)order.Total);

        return order;
    }
}

6. Azure Service Bus — Async Messaging Between Services

When Service A needs to tell Service B something happened, without waiting for a response, use Service Bus.

OrderAPI publishes "OrderCreated" → Service Bus → EmailService processes it

This decouples services. If EmailService is down, the message waits in the queue and gets processed when it comes back up.

Bash
dotnet add package Azure.Messaging.ServiceBus
C#
// Publisher
public class OrderPublisher
{
    private readonly ServiceBusSender _sender;

    public OrderPublisher(ServiceBusClient client)
        => _sender = client.CreateSender("orders");

    public async Task PublishOrderCreatedAsync(Order order)
    {
        var message = new ServiceBusMessage(JsonSerializer.Serialize(new
        {
            OrderId = order.Id,
            CustomerId = order.CustomerId,
            Total = order.Total,
            CreatedAt = order.CreatedAt
        }))
        {
            Subject = "OrderCreated",
            ContentType = "application/json"
        };

        await _sender.SendMessageAsync(message);
    }
}

// Consumer (background service)
public class OrderMessageConsumer : BackgroundService
{
    private readonly ServiceBusProcessor _processor;
    private readonly ILogger<OrderMessageConsumer> _logger;

    public OrderMessageConsumer(ServiceBusClient client, ILogger<OrderMessageConsumer> logger)
    {
        _processor = client.CreateProcessor("orders", "email-subscription");
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _processor.ProcessMessageAsync += HandleMessageAsync;
        _processor.ProcessErrorAsync += HandleErrorAsync;
        await _processor.StartProcessingAsync(stoppingToken);
    }

    private async Task HandleMessageAsync(ProcessMessageEventArgs args)
    {
        var json = args.Message.Body.ToString();
        _logger.LogInformation("Processing order message: {Body}", json);
        // Send email, update inventory, etc.
        await args.CompleteMessageAsync(args.Message);
    }

    private Task HandleErrorAsync(ProcessErrorEventArgs args)
    {
        _logger.LogError(args.Exception, "Service Bus error on {EntityPath}", args.EntityPath);
        return Task.CompletedTask;
    }
}

7. Azure Cache for Redis — Speed Up Your App

Azure Cache for Redis is a fully managed Redis instance. Use it for:

  • Caching database results
  • Session storage
  • Rate limiting counters
  • Pub/Sub messaging
Bash
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
C#
// Program.cs
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration["Redis:ConnectionString"];
    options.InstanceName = "MyApp:";
});

// Usage
public class ProductService
{
    private readonly IDistributedCache _cache;
    private readonly IProductRepository _products;

    public async Task<Product?> GetProductAsync(string id)
    {
        var cacheKey = $"product:{id}";
        var cached = await _cache.GetStringAsync(cacheKey);

        if (cached is not null)
            return JsonSerializer.Deserialize<Product>(cached);

        var product = await _products.GetByIdAsync(id);
        if (product is not null)
        {
            await _cache.SetStringAsync(cacheKey,
                JsonSerializer.Serialize(product),
                new DistributedCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15)
                });
        }

        return product;
    }
}

8. Azure Container Registry + Container Apps — Modern Deployment

For containerised apps, Azure Container Registry (ACR) stores your Docker images and Azure Container Apps runs them with auto-scaling.

Bash
# Build and push image to ACR
az acr create --name myregistry --resource-group MyRG --sku Basic
az acr login --name myregistry
docker build -t myregistry.azurecr.io/my-api:latest .
docker push myregistry.azurecr.io/my-api:latest

# Deploy to Container Apps
az containerapp create \
  --name my-api \
  --resource-group MyRG \
  --environment my-env \
  --image myregistry.azurecr.io/my-api:latest \
  --target-port 8080 \
  --ingress external \
  --min-replicas 1 \
  --max-replicas 10

Container Apps automatically scales to zero when idle (great for cost) and scales out under load.


The Architecture Pattern for a Typical .NET App on Azure

Browser / Mobile
       ↓
Azure App Service (ASP.NET Core API)
       ├── Azure SQL Database (relational data)
       ├── Azure Cache for Redis (caching + sessions)
       ├── Azure Blob Storage (files, images)
       ├── Azure Service Bus (async events)
       └── Azure Key Vault (secrets)
               ↓
    Application Insights (monitoring everything)

Local Development with Azure Services

You can use Azure services locally with the Azurite emulator (Storage) and real Azure dev resources:

Bash
# Azurite  local Azure Storage emulator
npm install -g azurite
azurite --loose

# For other services, create a dev resource group
az group create --name dev-MyProject --location norwayeast

For auth, DefaultAzureCredential picks up your Azure CLI session automatically:

Bash
az login
# Your app now authenticates to Azure services automatically from local dev

Key Takeaways

  1. App Service — deploy your API, handles SSL, scaling, and deployment slots
  2. Azure SQL — managed SQL Server with zero ops overhead
  3. Blob Storage — anything that isn't relational: files, images, backups
  4. Key Vault — secrets, never in config files
  5. Application Insights — observability, add it to every project from day one
  6. Service Bus — async decoupled communication between services
  7. Redis Cache — cache hot data, 100× faster than a database hit
  8. Container Apps — Kubernetes without the complexity

The next lesson covers deploying a .NET API to Azure App Service step by step — including CI/CD with GitHub Actions, environment-specific config, and production monitoring setup.

Enjoyed this article?

Explore the Backend Systems learning path for more.

Found this helpful?

Share:𝕏

Leave a comment

Have a question, correction, or just found this helpful? Leave a note below.