Browse narratives

EN · · 4 min read

Operating a .NET Service on Azure

A production-minded checklist for identity, configuration, observability, resilience, deployment, and cost.

Technical GuideIntermediateTime Bound

Revised

A service is not production-ready when it compiles, passes tests, or responds correctly on a laptop. It becomes production-ready when a team can deploy it safely, understand its behavior, recover from failure, and control its cost.

Azure offers a large catalogue of services, but choosing more services is not the same as designing a better system. I prefer to begin with operational questions and select the smallest platform surface that answers them.

Establish the runtime boundary

For a typical ASP.NET Core service, the first choice is not between every Azure product. It is whether the workload needs a managed web runtime, container orchestration, event-driven execution, or static delivery.

WorkloadStarting pointEscalate when
HTTP API or web applicationAzure App ServiceContainer/runtime constraints demand more control
Containerized serviceAzure Container AppsYou need Kubernetes-level control
Event-triggered short workAzure FunctionsExecution or networking constraints do not fit
Static Astro siteCloudflare Pages or Static Web AppsServer behavior becomes a real requirement

The starting point should minimize operational ownership. Complexity can be added after evidence appears.

Identity before secrets

Connection strings and API keys are easy locally and expensive operationally. On Azure, managed identity should be the default question for service-to-service access.

sequenceDiagram participant App as ASP.NET Core service participant Entra as Microsoft Entra ID participant Vault as Key Vault participant DB as Azure SQL/PostgreSQL App->>Entra: Request workload token Entra-->>App: Short-lived token App->>Vault: Read allowed configuration App->>DB: Connect with identity

This removes long-lived credentials from deployment settings, but it does not remove authorization work. The identity still needs the minimum role, environment boundaries, rotation behavior, and an auditable owner.

Configuration has a lifecycle

Configuration is more than key-value storage. Each value has scope, sensitivity, owner, default, and failure behavior. A service should validate required settings at startup so a bad deployment fails clearly rather than producing delayed runtime errors.

builder.Services
    .AddOptions<AuthorizationOptions>()
    .BindConfiguration("Authorization")
    .ValidateDataAnnotations()
    .ValidateOnStart();

Secrets belong in Key Vault or an equivalent secret store. Non-secret configuration can live in environment settings or App Configuration. Feature flags need expiration and ownership; otherwise temporary decisions become permanent branches.

Observability begins with questions

Logs, metrics, and traces are three views of behavior:

  • Metrics reveal trends and thresholds.
  • Traces reveal the path and latency of one operation.
  • Logs preserve contextual events that require explanation.

Instrument the boundaries first: incoming request, authorization decision, database call, external dependency, queue message, and background job. Use correlation identifiers consistently. Avoid logging payloads by default, especially tokens, personal data, and authorization tuples.

Resilience needs a failure model

Retries are not a universal reliability feature. They are appropriate only for transient failures and idempotent or protected operations. Unbounded retries multiply load during an outage.

timeout → bounded retry with jitter → circuit/open state → degraded response

Every dependency should have a time budget. Cancellation should flow from the HTTP request through application and data access layers. A queue consumer needs explicit poison-message and duplicate-delivery behavior.

Deployment is a reversible experiment

A safe deployment answers:

  1. What changed?
  2. How do we know it is healthy?
  3. What stops rollout?
  4. How do we return to a known state?
  5. Are database changes backward-compatible?

Blue/green slots or gradual revisions help, but the essential property is reversibility. Database migrations often define the real rollback boundary, so additive changes should precede destructive cleanup.

Cost is an architectural signal

Cost exposes architecture in aggregate: unnecessary data movement, idle capacity, noisy telemetry, and accidental fan-out eventually become visible on the bill.

Write the service contract before the deployment checklist

Operational readiness begins with explicit assumptions. What traffic shape is expected? Which operations may be retried? What data loss is acceptable? Which dependency failures should degrade the response and which should stop it? A list of Azure resources cannot answer these questions.

A compact service contract should record:

ConcernQuestion
AvailabilityWhich user journey must remain available?
DataWhat consistency and recovery point are required?
IdentityWhich workload may access each dependency?
ScaleWhat input or concurrency bound is expected?
RecoveryHow is a failed deployment reversed?
EvidenceWhich signals prove the service is healthy?

The cloud topology should follow these answers rather than lead them.

Rehearse one failure at a time

Dashboards are not evidence that recovery works. A small failure rehearsal can disable one dependency, expire one credential in a safe environment, saturate a bounded queue, or deploy a deliberately unhealthy revision. The objective is to observe detection, diagnosis, containment, and recovery.

Each rehearsal should produce a concrete improvement: a clearer alert, a safer timeout, a missing correlation field, or a runbook step that did not work as written. This is where resilience stops being configuration and becomes a team capability.

Warning

Azure product behavior and recommendations evolve. This article describes an operational method, not a permanent service-by-service configuration. Pin the environment and verify current platform guidance before applying it.

Operating a .NET service well means connecting code decisions to runtime evidence. Identity, telemetry, deployment, recovery, and cost are not the final chapter after development; they are constraints that shape the service from its first boundary.

Cost anomalies can expose inefficient query shapes, noisy telemetry, runaway retries, oversized compute, or poor cache behavior. Set budgets and alerts before the invoice becomes the monitoring system.

Production engineering is the practice of making behavior visible and change recoverable. Azure supplies mechanisms; the architecture must turn them into a coherent operating model.