Azure
intermediate
40-50 minutes

Advanced Azure Features

Master Azure SQL databases, Blob Storage, Key Vault, custom domains, monitoring, and production best practices.

What you'll accomplish

Production-ready Azure deployment with database, storage, secrets, and monitoring

Prerequisites

  • Application deployed to Azure
  • Basic understanding of Azure core concepts

Azure SQL Database

Fully managed SQL Server database.

Create SQL Server and Database

bash
# Create SQL Server
az sql server create \
  --name myapp-sqlserver \
  --resource-group myapp-rg \
  --location eastus \
  --admin-user sqladmin \
  --admin-password "SecureP@ssw0rd123!"

# Create database
az sql db create \
  --name myappdb \
  --server myapp-sqlserver \
  --resource-group myapp-rg \
  --edition Basic \
  --capacity 5

# For production
az sql db create \
  --name myappdb \
  --server myapp-sqlserver \
  --resource-group myapp-rg \
  --edition Standard \
  --service-objective S1

Pricing Tiers

TierDTUs/vCoresUse Case
Basic5 DTUDev/test
Standard S010 DTULight production
Standard S120 DTUSmall apps
Standard S250 DTUMedium apps
Premium P1125 DTUHigh performance

Configure Firewall

bash
# Allow Azure services
az sql server firewall-rule create \
  --server myapp-sqlserver \
  --resource-group myapp-rg \
  --name AllowAzureServices \
  --start-ip-address 0.0.0.0 \
  --end-ip-address 0.0.0.0

# Allow your IP
az sql server firewall-rule create \
  --server myapp-sqlserver \
  --resource-group myapp-rg \
  --name AllowMyIP \
  --start-ip-address YOUR_IP \
  --end-ip-address YOUR_IP

Connect from App Service

bash
# Get connection string
az sql db show-connection-string \
  --server myapp-sqlserver \
  --name myappdb \
  --client ado.net

# Set as connection string in App Service
az webapp config connection-string set \
  --name myapp \
  --resource-group myapp-rg \
  --connection-string-type SQLAzure \
  --settings DefaultConnection="Server=tcp:myapp-sqlserver.database.windows.net,1433;Database=myappdb;User ID=sqladmin;Password=YOUR_PASSWORD;Encrypt=true;"

PostgreSQL Alternative

bash
# Create PostgreSQL server
az postgres flexible-server create \
  --name myapp-postgres \
  --resource-group myapp-rg \
  --location eastus \
  --admin-user pgadmin \
  --admin-password "SecureP@ssw0rd123!" \
  --sku-name Standard_B1ms \
  --tier Burstable

# Create database
az postgres flexible-server db create \
  --server-name myapp-postgres \
  --resource-group myapp-rg \
  --database-name myappdb

Azure Blob Storage

Object storage for files, images, and backups.

Create Storage Account

bash
# Create storage account
az storage account create \
  --name myappstorage123 \
  --resource-group myapp-rg \
  --location eastus \
  --sku Standard_LRS \
  --kind StorageV2

# Get connection string
az storage account show-connection-string \
  --name myappstorage123 \
  --resource-group myapp-rg \
  --query connectionString \
  --output tsv

Create Container

bash
# Get storage key
STORAGE_KEY=$(az storage account keys list \
  --account-name myappstorage123 \
  --query "[0].value" \
  --output tsv)

# Create container
az storage container create \
  --name uploads \
  --account-name myappstorage123 \
  --account-key $STORAGE_KEY \
  --public-access off

Upload and Download Files

bash
# Upload file
az storage blob upload \
  --account-name myappstorage123 \
  --container-name uploads \
  --name myfile.txt \
  --file ./local-file.txt \
  --account-key $STORAGE_KEY

# List blobs
az storage blob list \
  --account-name myappstorage123 \
  --container-name uploads \
  --output table

# Download file
az storage blob download \
  --account-name myappstorage123 \
  --container-name uploads \
  --name myfile.txt \
  --file ./downloaded-file.txt \
  --account-key $STORAGE_KEY

Generate SAS Token

bash
# Generate SAS for container
END_DATE=$(date -u -d "+1 year" +%Y-%m-%dT%H:%MZ)

az storage container generate-sas \
  --account-name myappstorage123 \
  --name uploads \
  --permissions rwl \
  --expiry $END_DATE \
  --account-key $STORAGE_KEY

Static Website Hosting

bash
# Enable static website
az storage blob service-properties update \
  --account-name myappstorage123 \
  --static-website \
  --index-document index.html \
  --404-document 404.html

# Upload files
az storage blob upload-batch \
  --account-name myappstorage123 \
  --source ./dist \
  --destination '$web'

# Get website URL
az storage account show \
  --name myappstorage123 \
  --query "primaryEndpoints.web" \
  --output tsv

Azure Key Vault

Secure storage for secrets, keys, and certificates.

Create Key Vault

bash
az keyvault create \
  --name myapp-keyvault \
  --resource-group myapp-rg \
  --location eastus

Store and Retrieve Secrets

bash
# Add secret
az keyvault secret set \
  --vault-name myapp-keyvault \
  --name "DatabasePassword" \
  --value "supersecret123"

# Get secret
az keyvault secret show \
  --vault-name myapp-keyvault \
  --name "DatabasePassword" \
  --query value \
  --output tsv

# List secrets
az keyvault secret list \
  --vault-name myapp-keyvault \
  --output table

Access from App Service

bash
# Enable managed identity
az webapp identity assign \
  --name myapp \
  --resource-group myapp-rg

# Get identity principal ID
PRINCIPAL_ID=$(az webapp identity show \
  --name myapp \
  --resource-group myapp-rg \
  --query principalId \
  --output tsv)

# Grant access to Key Vault
az keyvault set-policy \
  --name myapp-keyvault \
  --object-id $PRINCIPAL_ID \
  --secret-permissions get list

# Reference secret in app settings
az webapp config appsettings set \
  --name myapp \
  --resource-group myapp-rg \
  --settings "[email protected](SecretUri=https://myapp-keyvault.vault.azure.net/secrets/DatabasePassword/)"

Custom Domains and SSL

Add Custom Domain to App Service

bash
# Add custom hostname
az webapp config hostname add \
  --webapp-name myapp \
  --resource-group myapp-rg \
  --hostname www.example.com

DNS Configuration

At your DNS provider:

TypeNameValue
CNAMEwwwmyapp.azurewebsites.net
TXTasuid.www(from Azure verification)

For apex domain:

TypeNameValue
A@App Service IP
TXTasuid(from Azure verification)

Free Managed SSL

bash
# Create managed certificate
az webapp config ssl create \
  --name myapp \
  --resource-group myapp-rg \
  --hostname www.example.com

# Bind certificate
az webapp config ssl bind \
  --name myapp \
  --resource-group myapp-rg \
  --certificate-thumbprint THUMBPRINT \
  --ssl-type SNI

# Enforce HTTPS
az webapp update \
  --name myapp \
  --resource-group myapp-rg \
  --https-only true

Application Insights

Full application monitoring.

Enable Application Insights

bash
# Create Application Insights
az monitor app-insights component create \
  --app myapp-insights \
  --resource-group myapp-rg \
  --location eastus \
  --application-type web

# Get instrumentation key
az monitor app-insights component show \
  --app myapp-insights \
  --resource-group myapp-rg \
  --query instrumentationKey \
  --output tsv

# Connect to App Service
az monitor app-insights component connect-webapp \
  --app myapp-insights \
  --resource-group myapp-rg \
  --web-app myapp

View Metrics

bash
# Query metrics
az monitor app-insights metrics show \
  --app myapp-insights \
  --resource-group myapp-rg \
  --metric requests/count \
  --interval PT1H

Create Alerts

bash
# Create alert for high error rate
az monitor metrics alert create \
  --name "High Error Rate" \
  --resource-group myapp-rg \
  --scopes /subscriptions/.../resourceGroups/myapp-rg/providers/Microsoft.Web/sites/myapp \
  --condition "total requests/failed > 10" \
  --window-size 5m \
  --evaluation-frequency 1m

Azure Monitor and Logging

Enable Diagnostic Logs

bash
# Enable all logs
az webapp log config \
  --name myapp \
  --resource-group myapp-rg \
  --application-logging filesystem \
  --detailed-error-messages true \
  --failed-request-tracing true \
  --web-server-logging filesystem \
  --level information

# Stream logs
az webapp log tail \
  --name myapp \
  --resource-group myapp-rg

Log Analytics Workspace

bash
# Create workspace
az monitor log-analytics workspace create \
  --workspace-name myapp-logs \
  --resource-group myapp-rg \
  --location eastus

# Query logs
az monitor log-analytics query \
  --workspace myapp-logs \
  --analytics-query "AppServiceHTTPLogs | where ScStatus >= 500 | take 10"

Azure Front Door (CDN)

Global CDN and load balancing.

bash
# Create Front Door profile
az afd profile create \
  --profile-name myapp-frontdoor \
  --resource-group myapp-rg \
  --sku Standard_AzureFrontDoor

# Create endpoint
az afd endpoint create \
  --endpoint-name myapp-endpoint \
  --profile-name myapp-frontdoor \
  --resource-group myapp-rg

# Create origin group
az afd origin-group create \
  --origin-group-name myapp-origin-group \
  --profile-name myapp-frontdoor \
  --resource-group myapp-rg \
  --probe-path /health \
  --probe-protocol Https \
  --probe-request-type HEAD \
  --probe-interval-in-seconds 30

# Add origin
az afd origin create \
  --origin-name myapp-origin \
  --origin-group-name myapp-origin-group \
  --profile-name myapp-frontdoor \
  --resource-group myapp-rg \
  --host-name myapp.azurewebsites.net \
  --origin-host-header myapp.azurewebsites.net \
  --http-port 80 \
  --https-port 443 \
  --priority 1 \
  --weight 1000

# Create route
az afd route create \
  --route-name myapp-route \
  --endpoint-name myapp-endpoint \
  --profile-name myapp-frontdoor \
  --resource-group myapp-rg \
  --origin-group myapp-origin-group \
  --patterns-to-match "/*" \
  --supported-protocols Https \
  --https-redirect Enabled

Azure Backup

App Service Backup

bash
# Create storage container for backups
az storage container create \
  --name backups \
  --account-name myappstorage123

# Configure backup
az webapp config backup create \
  --webapp-name myapp \
  --resource-group myapp-rg \
  --container-url "https://myappstorage123.blob.core.windows.net/backups?SAS_TOKEN" \
  --frequency 1d \
  --retain-one true

Database Backup

Azure SQL has automatic backups:

  • Point-in-time restore (7-35 days)
  • Long-term retention (up to 10 years)
bash
# Configure long-term retention
az sql db ltr-policy set \
  --server myapp-sqlserver \
  --database myappdb \
  --resource-group myapp-rg \
  --weekly-retention P4W \
  --monthly-retention P12M \
  --yearly-retention P5Y \
  --week-of-year 1

Cost Management

Set Budget

bash
az consumption budget create \
  --amount 100 \
  --budget-name "Monthly Budget" \
  --category Cost \
  --resource-group myapp-rg \
  --time-grain Monthly \
  --time-period start-date=$(date +%Y-%m-01) \
  --notifications type="Actual" contact-emails="[email protected]" threshold=80

View Costs

bash
# Get current costs
az consumption usage list \
  --start-date $(date -d "-7 days" +%Y-%m-%d) \
  --end-date $(date +%Y-%m-%d) \
  --output table

Cost Saving Tips

  1. Use reserved instances - Up to 72% savings
  2. Right-size resources - Monitor and adjust
  3. Use dev/test subscriptions - Lower rates
  4. Auto-shutdown VMs - Off-hours savings
  5. Use serverless - Pay per execution
  6. Delete unused resources - IPs, disks, snapshots

Production Checklist

Security

  • Enable managed identity
  • Store secrets in Key Vault
  • Configure HTTPS only
  • Set up firewall rules
  • Enable Azure AD authentication
  • Review RBAC permissions

Reliability

  • Configure auto-scaling
  • Set up deployment slots
  • Enable health checks
  • Configure database backups
  • Test disaster recovery

Performance

  • Enable Azure CDN/Front Door
  • Configure caching headers
  • Use connection pooling
  • Optimize database queries
  • Monitor Application Insights

Monitoring

  • Enable Application Insights
  • Configure alerts
  • Set up Log Analytics
  • Create dashboards
  • Set budget alerts

Deployment

  • Set up CI/CD pipeline
  • Use staging slots
  • Implement health checks
  • Configure rollback strategy

Complete Production Setup

bash
#!/bin/bash
set -e

RESOURCE_GROUP="myapp-prod-rg"
LOCATION="eastus"
APP_NAME="myapp-prod"

# Create resource group
az group create --name $RESOURCE_GROUP --location $LOCATION

# Create App Service plan
az appservice plan create \
  --name ${APP_NAME}-plan \
  --resource-group $RESOURCE_GROUP \
  --sku S1 \
  --is-linux

# Create web app
az webapp create \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --plan ${APP_NAME}-plan \
  --runtime "NODE:20-lts"

# Enable managed identity
az webapp identity assign \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP

# Create Key Vault
az keyvault create \
  --name ${APP_NAME}-kv \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION

# Grant Key Vault access
PRINCIPAL_ID=$(az webapp identity show \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --query principalId -o tsv)

az keyvault set-policy \
  --name ${APP_NAME}-kv \
  --object-id $PRINCIPAL_ID \
  --secret-permissions get list

# Create SQL Database
az sql server create \
  --name ${APP_NAME}-sql \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --admin-user sqladmin \
  --admin-password "$(openssl rand -base64 24)"

az sql db create \
  --name ${APP_NAME}db \
  --server ${APP_NAME}-sql \
  --resource-group $RESOURCE_GROUP \
  --edition Standard \
  --service-objective S1

# Create storage account
az storage account create \
  --name ${APP_NAME}storage \
  --resource-group $RESOURCE_GROUP \
  --sku Standard_LRS

# Create Application Insights
az monitor app-insights component create \
  --app ${APP_NAME}-insights \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --application-type web

az monitor app-insights component connect-webapp \
  --app ${APP_NAME}-insights \
  --resource-group $RESOURCE_GROUP \
  --web-app $APP_NAME

# Enable HTTPS only
az webapp update \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --https-only true

# Enable always on
az webapp config set \
  --name $APP_NAME \
  --resource-group $RESOURCE_GROUP \
  --always-on true

echo "Production setup complete!"
echo "App URL: https://${APP_NAME}.azurewebsites.net"
Note

Checkpoint: Set up Azure SQL, configure Key Vault for secrets, enable Application Insights, and verify your production checklist is complete.