Trust is earned, not given

A different perspective

2019-08-14 · Projects

DevOps on Azure, part 3: Data — Azure SQL, Cosmos DB, Blob Storage, and Redis

Part 3from the DevOps on Azure series · 6 parts in all

Part 3: the data layer. Azure's data services are unusually opinionated about serverlessness and private connectivity, and those two opinions shape everything.

Azure SQL Database: SQL Server without the server

MapleCart's orders live in Azure SQL, in the serverless compute tier — auto-pausing when idle, auto-resuming on connection (billed per second of actual use):

az sql server create -g maplecart-rg -n maplecart-sql \
  --admin-user mapleadmin --admin-password <from-keyvault> -l westus2

az sql db create -g maplecart-rg -s maplecart-sql -n orders \
  --service-objective GP_S_Gen5_2 \            # serverless: 2 vCore, autoscale+autopause
  --backup-storage-redundancy Zone \
  --min-capacity 0.5 --auto-pause-delay 60     # pause after 1 idle hour

# Private connectivity: a private endpoint puts SQL inside the VNet
az network private-endpoint create -g maplecart-rg -n sql-pe --vnet-name maplecart-vnet \
  --subnet app-subnet --private-connection-resource-id <sql-resource-id> --group-id sqlServer

The private endpoint is the pattern to steal: the SQL server gets a private IP inside the VNet and its public surface can be disabled entirely. Combined with the app's managed identity, the connection string contains no password at all — the database trusts the Entra identity of the app:

# C# (the app): identity-based connection - no user, no password
var conn = new SqlConnectionStringBuilder
{
    Server  = "maplecart-sql.database.windows.net",
    Database = "orders",
    Authentication = SqlAuthenticationMethod.ActiveDirectoryDefault,  // managed identity
    Encrypt = true
};

Cosmos DB: the planet-scale key-value/document store

FleetView's telemetry goes to Cosmos DB. The one decision that matters is the partition key — it decides how data spreads across the physical partitions. For per-tenant workloads: /tenant_id, so one tenant's queries hit one partition and hot tenants can't strangle others:

az cosmosdb create -g fleetview-rg -n fleetview-cosmos \
  --capabilities EnableServerless            # serverless: pay per request

# Python SDK: insert telemetry; TTL auto-expires rows after 90 days
from azure.cosmos import CosmosClient
client = CosmosClient(url, credential=credential)   # Entra identity via DefaultAzureCredential
container = client.get_database_client("telemetry").get_container_client("pings")
container.upsert_item({
    "id": str(uuid4()),
    "tenant_id": tenant,                       # partition key
    "device": device, "ts": ts.isoformat(),
    "speed_kph": speed,
    "ttl": 90 * 24 * 3600,                     # auto-delete after 90 days
})

Blob Storage and Redis

Blob Storage (S3's cousin) hosts NewsGrid's static site and MapleCart's product images — with lifecycle rules that age cold blobs to Cool/Archive tiers automatically. Redis Enterprise/Standard backs MapleCart's catalog cache with the same cache-aside pattern as the AWS series. Nothing conceptually new — which is the point: the data layer is portable knowledge.

Next: the network and identity skeleton — VNet, NSGs, private endpoints, and managed identities everywhere.