Skip to main content

Database Deployment Automation — ARM, Bicep, PowerShell & CLI

Automating database deployment ensures consistency, repeatability, and auditability. No manual portal clicks in production — everything as code.

Infrastructure as Code (IaC) Options

ToolTypeBest ForLearning Curve
ARM TemplatesJSON declarativeLegacy deployments, complex dependenciesHigh
BicepDSL (compiles to ARM)All new Azure deploymentsLow-Medium
TerraformHCL declarativeMulti-cloud, team standardizationMedium
PowerShell (Az module)Imperative scriptingQuick tasks, automation runbooksLow
Azure CLIImperative CLIBash-friendly, CI/CD pipelinesLow
🎯 Exam Focus

DP-300 focus: You need to understand ARM/Bicep for declarative deployments, and PowerShell/CLI for imperative operations. Know the difference: declarative = "this is what I want" (ARM/Bicep/Terraform), imperative = "do this step by step" (PowerShell/CLI).

ARM Templates vs Bicep

AspectARM TemplateBicep
FormatJSONDSL (cleaner syntax)
ReadabilityVerbose, nestedClean, concise
ModulesNested templatesNative module support
ParametersJSON param files.bicepparam files
IntellisenseLimitedFull VS Code support
OutputJSON ARM templateCompiles to ARM JSON
Microsoft recommendationLegacy✅ Recommended
🏢 Real-World DBA Note

Always use Bicep for new deployments. ARM JSON templates are still supported but Bicep is Microsoft's recommended approach. Bicep files are 60-80% shorter than equivalent ARM JSON and have full VS Code IntelliSense.

What Can You Deploy?

ResourceBicep/ARMPowerShell/CLI
Logical SQL Server
Azure SQL Database
Elastic Pool
Managed Instance
Failover Group
Firewall Rules
Private Endpoint
SQL VM (IaaS)
VNet + NSG
Auditing + ATP

Deployment Patterns

Pattern 1: Full Environment (Bicep)

Deploy a complete environment in one command:

  • VNet + Subnet + NSG
  • Logical SQL Server + Databases
  • Firewall rules + Private Endpoint
  • Auditing → Log Analytics
  • Failover Group (cross-region)

This is the recommended production pattern — everything defined in code, version-controlled, repeatable.

Pattern 2: Database-Level Changes (PowerShell/CLI)

Day-to-day operations after initial deployment:

  • Scale vCores up/down
  • Change backup retention
  • Add/remove databases from elastic pool
  • Configure auto-tuning
  • Manage firewall rules

Pattern 3: CI/CD Pipeline (Azure DevOps / GitHub Actions)

Automated deployment on every code push:

  1. Developer commits Bicep/SQL script to Git
  2. Pipeline validates (what-if / plan)
  3. Approval gate for production
  4. Deploy infrastructure changes
  5. Deploy schema changes (DACPAC/SSDT)

Schema Deployment Tools

ToolWhat It DoesBest For
SSDT (SQL Server Data Tools)Visual Studio project for database schemaSchema version control, diff-based deploy
DACPACCompiled schema packageCI/CD pipeline schema deployment
SqlPackage.exeCLI tool to deploy DACPACsAutomation, cross-platform
dbup / Flyway / LiquibaseMigration-based schema changesIncremental migration scripts
EF Core MigrationsORM-based schema management.NET application teams
🎯 Exam Focus

DACPAC (Data-tier Application Package) is a key DP-300 concept. It contains a database schema definition and can be used to deploy schema changes or extract/import database structures. SqlPackage.exe is the CLI tool for DACPAC operations.

Azure DevOps Pipeline for SQL

A typical pipeline:

StageWhat Happens
BuildCompile SSDT project → produce DACPAC
ValidateRun what-if against target DB (dry run)
Deploy to DevAuto-deploy DACPAC to dev environment
TestRun integration tests against dev DB
Deploy to StagingDeploy to staging with approval gate
Deploy to ProdManual approval → deploy to production

Key Deployment Concepts

Idempotency

Declarative deployments (Bicep/ARM) are idempotent — running the same template twice produces the same result without errors. This is critical for reliable automation.

What-If / Preview

Always preview changes before deploying:

  • Bicep/ARM: az deployment group what-if
  • Terraform: terraform plan
  • DACPAC: SqlPackage /Action:DeployReport

State Management

ToolState
ARM/BicepAzure manages state (resource-level)
Terraform.tfstate file (you manage — use remote backend)
PowerShell/CLINo state (imperative = you track manually)
⚠️ Watch Out

Never deploy infrastructure changes from a developer's laptop to production. Always use a CI/CD pipeline with approval gates, audit logging, and rollback capability. Treat database deployments with the same rigor as application deployments.


Anti-Patterns

  • "Deploy infra and schema in the same pipeline stage." Couples infra failures to schema rollbacks. Separate stages: infra (Bicep) → schema (DACPAC / migrations) → app (release).
  • "DACPAC ‘Drop objects not in source’ enabled in prod." Will silently delete tables that have data but aren't in the project. Disable in prod publish profiles; allow only in dev/test.
  • "Run schema migrations from the deploying user's account." Should run as a scoped pipeline identity with db_ddladmin only. Don't reuse the dev's account.
  • "Roll back schema by re-running an old DACPAC." Schema is one-way for many changes (dropped columns can't be recovered without backup). Always backup before deploy and test rollback.
  • "Single Bicep file = whole production." Monolithic templates hit the deployment depth/size limits. Break into modules + subscription-scope deployments.
  • "Trust --no-prompt on every change." DACPAC and azd flags that suppress prompts also suppress useful warnings. Read the pre-deploy report before merging the PR.
⚠️ Watch Out

azd up runs azd provision + azd deploy — it provisions infra AND publishes app code. For infra-only changes use azd provision. For app-only deploys use azd deploy. Mixing them in CI without intent re-deploys both unnecessarily.


Migration Between Deployment Pipelines

From → ToPathCost
Manual portal deploy → GitHub ActionsWire OIDC + what-if on PROne-time setup; gains audit trail
Imperative scripts → Bicep + modulesRefactor; adopt AVM where possibleDeclarative; smaller diff per change
Bicep → TerraformRewrite in HCL; migrate stateMulti-cloud option; state file mgmt
Hand-written pipelines → azd templateAdopt azd init + azure.yamlLower boilerplate; opinionated
Schema in app pipeline → separate schema pipelineSplit DACPAC stage; gate behind approvalClearer ownership; longer release window
DACPAC → EF Core migrationsAdopt EF migrations; deprecate DACPACCode-driven; less schema drift
Direct prod deploy → ring deployment (canary)Stage → 5 % → 50 % → 100 %Catches regressions early; pipeline complexity
Push deploy → GitOps (Flux/Argo)Reconciler watches repo → clusterSelf-healing; setup cost

Most expensive moves: DACPAC → EF migrations (schema philosophy change) and Bicep → Terraform (HCL rewrite + state).


Real Scenarios

  1. Greenfield SaaS, single teamazd template + Bicep + GitHub Actions + DACPAC for schema. Driver: lowest scaffold time. Trade-off: opinionated structure.
  2. Enterprise with platform team → product teamsPlatform team owns Bicep modules in private registry; product teams consume via br: references. Driver: standardization + autonomy. Trade-off: registry maintenance.
  3. Multi-region SQL DB schema changePipeline runs DACPAC on primary; FOG replicates to secondary. Driver: avoid divergence. Trade-off: replication lag visible during deploy.
  4. Compliance: every change auditableBranch protection + reviewer required + signed commits + Bicep what-if artifact stored in pipeline. Driver: regulator evidence. Trade-off: PR cycle time.
  5. High-velocity dev, low-blast-radius envPR → ephemeral environment via azd up → auto-delete after merge. Driver: testing in isolation. Trade-off: cost per PR (mitigate with TTL).

Flashcards

What is the difference between declarative and imperative deployment?
Click to reveal answer
Declarative (Bicep/ARM/Terraform): 'This is what I want' — the tool figures out how. Imperative (PowerShell/CLI): 'Do this step by step' — you control the sequence.
1 / 5

Quiz

Q1/5
0 correct
Your team needs to deploy identical Azure SQL environments for dev, staging, and production. What approach should you use?