GMI · TECHNOLOGY OBSERVATORY // ALL SYSTEMS NOMINAL
ENGINEERED BY LEOPARD DATA

Why Azure

The cloud choice explained: every Azure object GMI runs on, its scaling limits, how the platform grows with the cloud — and the honest admission that AWS or Google Cloud could host this system too

GROWING WITH AZURE
rendering diagram…
flowchart LR
    subgraph T[Today ~$175/mo: 300-500 users]
      A1[App Services: Basic]
      A2[Functions: B-series]
      A3[MySQL: Burstable<br/>171 connections]
      A4[Worker VM: B-series]
    end
    subgraph S1[First step ~$240/mo: 1,500-2,500 users]
      B1[MySQL SKU step:<br/>connections + memory double]
      B2[Functions/App SKU step]
    end
    subgraph S2[Beyond: same shape, bigger dials]
      C1[Read replicas + caching]
      C2[More worker VMs on<br/>the same job queue]
      C3[CDN in front of<br/>static surfaces]
    end
    T --> S1 --> S2
    T -. architecture unchanged<br/>at every step .-> S2
Every resource has a dial that turns independently — and none of the dials require re-architecture. The platform's shape stays constant from 10 users to 10,000.

The Choice, Honestly Stated

GMI chose Azure for a simple, unromantic reason: this is a Microsoft-stack system — .NET 10 everywhere, Blazor on the web, MAUI on mobile, Entra ID for admin identity, Azure DevOps for CI/CD (see Why Microsoft Technology). Azure is where that stack has first-party citizenship: Functions run .NET isolated workers natively, App Service understands ASP.NET deployment idioms, Entra integrates without federation gymnastics, and one identity spans code, pipelines, and cloud.

But honesty over dogma, as everywhere on this site: GMI is not architecturally married to Azure. The platform is plain .NET, MySQL, blob storage, and Linux processes — the most portable combination in modern computing. AWS or Google Cloud could host this system with equivalent objects (the matrix below maps them one-to-one), and the infrastructure-as-code layer (Pulumi) is itself multi-cloud. We went with Azure because the stack pointed there — not because the doors are locked.

Every Azure Object, Its Limits, and Its Dial

Azure objectRole in GMIToday's limitThe growth dial
App Service ×3 (Basic, Windows)Client Web (WASM + static), Admin Web, Technology siteStatic serving — practically traffic-indifferent at this tierSKU up (S/P tiers), instances out, CDN in front as a bolt-on
Functions App (Linux plan, B-series)The 336-endpoint API + share/card renderingPlan compute; stateless workersScale up or out linearly; Premium plan for pre-warmed instances if latency ever demands it
MySQL Flexible Server (Burstable)All 69 tables + job queues — the system of record171 connections — the platform's first scaling wallSKU steps double connections/memory; General Purpose tier; read replicas for read-heavy load. Watched first because it scales hardest
Linux VM (B-series)The 15-service worker fleet: reports, ML, SEO/card builds, billingvCPU/RAM bound on batch throughputBigger VM for heavier jobs, or more VMs polling the same DB job queue — horizontal by design
Blob Storage ×2 (Standard LRS + ZRS)Reports, raw data, generated pages, social cardsNone that matter — petabyte-classThe dial is a credit card, not a decision
Key VaultSecrets: API keys, connection strings, OAuthNot a scaling concern
Entra IDAdmin identity + RBACNot a scaling concern
VNet + NSGsNetwork isolation for VM and FunctionsNot a scaling concern
Application InsightsTelemetry, dependencies, exceptionsIngestion-pricedSampling already on; caps configurable
Azure DevOpsRepos + the CI/CD pipeline for every appOne hosted build laneParallel-job purchase if build queue ever matters

The through-line: compute and database have dials; identity, secrets, and networking are set-and-forget; storage is unlimited. Capacity today is ~300–500 users at ~$175/month, with the first SKU step (~$240/month) reaching an estimated 1,500–2,500 — full math on the Lean Cloud Economics page.

The Same System on AWS or Google Cloud — the Portability Matrix

Could GMI run on the other hyperscalers? Yes — object for object. This matrix is the honest proof that the architecture, not the vendor, is the asset:

RoleAzure (chosen)AWS equivalentGoogle Cloud equivalent
Web app hostingApp ServiceElastic Beanstalk / App RunnerCloud Run / App Engine
API computeAzure Functions (isolated .NET)Lambda + API GatewayCloud Run / Cloud Functions
Relational databaseMySQL Flexible ServerRDS for MySQL / Aurora MySQLCloud SQL for MySQL
Worker fleetLinux VM (systemd services)EC2Compute Engine
Object storageBlob StorageS3Cloud Storage
SecretsKey VaultSecrets ManagerSecret Manager
Admin identityEntra IDIAM Identity Center / CognitoCloud Identity / Identity Platform
TelemetryApplication InsightsCloudWatch + X-RayCloud Monitoring / Trace
NetworkingVNet + NSGsVPC + Security GroupsVPC + Firewall Rules
CI/CDAzure DevOps PipelinesCodePipeline / GitHub ActionsCloud Build / GitHub Actions
Infrastructure-as-codePulumi — already multi-cloud; the same C# IaC style targets all three

What would actually change in a migration: connection strings, the identity integration for the admin portal, and pipeline YAML. What wouldn't: the 312K lines of application code, the schema, the job-queue pattern, or the architecture. That's the payoff of building on boring, portable primitives — the cloud is a supplier, not a landlord. Azure earns the business by fitting the stack best; it keeps the business the same way.