14 Years of Enterprise ASP.NET, Part 4: Azure, Observability & AI in Real Systems A developer with 14 years of enterprise ASP.NET experience details architectural decisions for a .NET 9 system serving 110,000 monthly active users, emphasizing right-sizing Azure compute to save $2,000 per month and implementing OpenTelemetry-based observability to cut mean-time-to-diagnose from 35 minutes to 4. The project treats AI as a production component, using grounded RAG to deflect about 520 support tickets monthly and classical ML via ML.NET for in-process predictions. Originally published at prepstack.co.in Part 4 of 4 —Where the system actually runs: choosing Azure architecture by cost and scaling profile, making the system observable, and treating AI as a real architectural component — not a demo.14 Years of Enterprise ASP.NET finale . Running example: Mattrx — .NET 9 / ASP.NET Core, 110k MAU, Azure SQL, ~3,200 req/sec peak. Pick the compute by your scaling and operational profile, then right-size — don't default to the biggest box or the trendiest platform. Most enterprise .NET runs perfectly on Azure App Service; you reach for Container Apps or AKS when you have a specific reason, not because Kubernetes is on your résumé. The decision framework: App Service for standard web/API default , Container Apps when you want containers + scale-to-zero without running a cluster, AKS only when you genuinely need its control plane and have the ops capacity. A 5-person team has no business running Kubernetes. Over-provisioning is the most common and most invisible cloud waste — it never pages anyone, so nobody fixes it. Right-sizing the web tier P2v3×6 always-on → P1v3×2 + autoscale , moving to managed Redis, and tuning the SQL tier saved roughly $2,000/month total — with better peak headroom, because autoscale handles the month-end burst the fixed fleet was over-sized for. For years I "had logging" and was still blind in production. The shift from logging to observability — answering new questions about a running system without shipping new code — is the difference between a 4-minute incident and a 4-hour one. You can't fix what you can't see, and you can't see what you didn't instrument. Three pillars, tied by a correlation ID: logs what happened , metrics how much/how often , traces where the time went . // structured fields + a correlation scope so every line in the request is linkable using logger.BeginScope new Dictionary