Skip to main content

Azure SQL vs Cosmos DB vs PostgreSQL — Choose the Right Database

· 7 min read
Goel Academy
DevOps & Cloud Learning Hub

You have just built a brilliant application. Now comes the question that has sparked a thousand architecture review meetings: which database? Azure offers over a dozen managed database services, and picking the wrong one means either rewriting your data layer six months later or paying triple what you should. Let's cut through the confusion and build a real decision framework.

The Decision Tree

Before diving into individual services, start with three questions:

  1. Is your data relational? If you need joins, transactions, and foreign keys, go relational.
  2. Do you need global distribution? If your users are on every continent and need single-digit millisecond reads, Cosmos DB is built for this.
  3. What is your query pattern? Known schemas with complex queries favor SQL. Flexible, document-oriented access patterns favor NoSQL.

If you answered "relational" and your team already knows PostgreSQL, stop reading and go with Azure Database for PostgreSQL. If you need SQL Server compatibility, go Azure SQL Database. If you need multi-model, globally distributed, or massive write throughput, Cosmos DB is your answer.

Azure SQL Database

Azure SQL Database is a fully managed relational database built on the SQL Server engine. You get automatic patching, backups, and high availability without managing a VM.

DTU vs vCore Pricing

This is where people get confused. Azure SQL Database offers two purchasing models:

ModelWhat It IsBest ForScaling
DTUBundled CPU + Memory + IO unitsPredictable workloads, simpler billingBasic (5 DTU) to Premium (4000 DTU)
vCoreChoose CPU cores and memory independentlyFlexible sizing, reserved capacity discounts2 to 128 vCores

DTU is simpler — you pick a tier and get a pre-configured bundle. vCore gives you control over individual resources and lets you bring your own SQL Server license (Azure Hybrid Benefit).

Creating an Azure SQL Database

# Create a resource group
az group create \
--name rg-database-demo \
--location eastus

# Create a SQL Server (logical server)
az sql server create \
--resource-group rg-database-demo \
--name sql-server-prod-2025 \
--admin-user sqladmin \
--admin-password 'YourStr0ngP@ssw0rd!' \
--location eastus

# Create a database with vCore model (General Purpose, 2 vCores)
az sql db create \
--resource-group rg-database-demo \
--server sql-server-prod-2025 \
--name db-inventory \
--edition GeneralPurpose \
--family Gen5 \
--capacity 2 \
--max-size 32GB

Elastic Pools

If you run multiple databases with unpredictable usage spikes, elastic pools let them share resources:

# Create an elastic pool
az sql elastic-pool create \
--resource-group rg-database-demo \
--server sql-server-prod-2025 \
--name pool-shared-prod \
--edition GeneralPurpose \
--family Gen5 \
--capacity 4 \
--max-size 128GB

# Move a database into the pool
az sql db update \
--resource-group rg-database-demo \
--server sql-server-prod-2025 \
--name db-inventory \
--elastic-pool pool-shared-prod

Ten databases each sized for peak load would cost a fortune. Ten databases in an elastic pool share a common resource ceiling — one spikes while others idle.

Azure Database for PostgreSQL — Flexible Server

If your team thinks in PostgreSQL and you want a managed service that actually feels like PostgreSQL, Flexible Server is the answer. It replaced the older Single Server offering and gives you full control over PostgreSQL extensions, parameters, and versions.

# Create a PostgreSQL Flexible Server
az postgres flexible-server create \
--resource-group rg-database-demo \
--name pg-flex-prod-2025 \
--location eastus \
--admin-user pgadmin \
--admin-password 'P0stgres$ecure!' \
--sku-name Standard_D2ds_v4 \
--tier GeneralPurpose \
--storage-size 128 \
--version 16 \
--high-availability ZoneRedundant

The connection string follows standard PostgreSQL format:

# Connect using psql
psql "host=pg-flex-prod-2025.postgres.database.azure.com \
port=5432 \
dbname=postgres \
user=pgadmin \
sslmode=require"

Cosmos DB — Multi-Model Global Distribution

Cosmos DB is Azure's globally distributed, multi-model database. It handles documents (NoSQL API), graph (Gremlin), key-value (Table), column-family (Cassandra), and even PostgreSQL (via the PostgreSQL API). But its sweet spot is the NoSQL API for JSON document workloads with global reach.

Consistency Levels

This is what makes Cosmos DB unique. Instead of forcing you into "strong or eventual," it offers five tunable consistency levels:

LevelGuaranteeLatencyUse Case
StrongLinearizable readsHighestFinancial transactions
Bounded StalenessReads lag by at most K versions or T secondsHighLeaderboards, inventory counts
SessionRead-your-own-writes within a sessionMediumUser profiles, shopping carts
Consistent PrefixReads never see out-of-order writesLowSocial feeds, activity logs
EventualNo ordering guaranteeLowestAnalytics, logging

Session consistency is the default and the right choice for 90% of applications.

Creating a Cosmos DB Account

# Create a Cosmos DB account (NoSQL API)
az cosmosdb create \
--resource-group rg-database-demo \
--name cosmos-prod-2025 \
--kind GlobalDocumentDB \
--locations regionName=eastus failoverPriority=0 \
--locations regionName=westeurope failoverPriority=1 \
--default-consistency-level Session \
--enable-automatic-failover true

# Create a database
az cosmosdb sql database create \
--resource-group rg-database-demo \
--account-name cosmos-prod-2025 \
--name OrdersDB

# Create a container with partition key
az cosmosdb sql container create \
--resource-group rg-database-demo \
--account-name cosmos-prod-2025 \
--database-name OrdersDB \
--name Orders \
--partition-key-path /customerId \
--throughput 400

Provisioned vs Serverless Throughput

Cosmos DB charges for Request Units (RU/s). You have two options:

  • Provisioned throughput: You set RU/s upfront (400-1,000,000). Best for production with predictable traffic.
  • Serverless: Pay per operation. Best for dev/test or sporadic workloads.

The Comparison Table

FeatureAzure SQL DatabasePostgreSQL Flexible ServerCosmos DB
TypeRelational (SQL Server)Relational (PostgreSQL)Multi-model (NoSQL primary)
Best ForEnterprise apps, ERP, .NET stacksOpen-source stacks, analyticsGlobal apps, IoT, real-time
ScalingVertical (DTU/vCore) + Read replicasVertical + Read replicasHorizontal (partitioning) + Global
Global DistributionGeo-replication (async)Read replicas (limited regions)Multi-region writes (native)
ConsistencyStrong (ACID)Strong (ACID)5 tunable levels
Pricing ModelDTU or vCoreCompute + StorageRU/s + Storage
Starting Cost~$5/month (Basic DTU)~$12/month (Burstable B1ms)Free tier (1000 RU/s)
Max Storage4 TB (100 TB Hyperscale)16 TBUnlimited
BackupAutomated (7-35 days)Automated (7-35 days)Continuous (point-in-time)

Backup and Restore

Every database needs a recovery story. Here is how each service handles it:

# Azure SQL — restore to a point in time
az sql db restore \
--resource-group rg-database-demo \
--server sql-server-prod-2025 \
--name db-inventory-restored \
--dest-name db-inventory-restored \
--time "2025-05-09T10:00:00Z"

# PostgreSQL — restore to a point in time
az postgres flexible-server restore \
--resource-group rg-database-demo \
--name pg-flex-restored \
--source-server pg-flex-prod-2025 \
--restore-time "2025-05-09T10:00:00Z"

# Cosmos DB — continuous backup is automatic
# Restore to a point in time (creates a new account)
az cosmosdb restore \
--resource-group rg-database-demo \
--account-name cosmos-prod-2025 \
--target-database-account-name cosmos-restored-2025 \
--restore-timestamp "2025-05-09T10:00:00Z" \
--location eastus

Wrapping Up

The right database is the one that matches your data model, scale requirements, and team skills. Azure SQL Database is the safe choice for relational workloads in Microsoft-centric environments. PostgreSQL Flexible Server is the go-to for open-source teams who want managed infrastructure without vendor lock-in. Cosmos DB is the right answer when you need global distribution, massive throughput, or flexible consistency — but it demands careful partition key design and RU planning. Pick one, learn it deeply, and remember: you can always add a second database for a different workload later.


Next up: We will dive into Azure Functions — building serverless compute that scales to zero and triggers from almost anything.