Azure Cost Estimate — linux-update-cds¶
Disclaimer: All prices are Azure Commercial list prices in USD, East US region, as of mid-2025. Figures exclude applicable taxes, EA/MCA discounts, Azure Hybrid Benefit, Savings Plans, and Reserved Instance pricing. Actual bills will differ. This is not a quote. Always verify current prices at the Azure Pricing Calculator and Azure Government Pricing.
Resource inventory¶
The following SKUs are read directly from the Bicep modules in infra/low-side/. Defaults are the
values that take effect when no override is provided in the .bicepparam file.
| Resource | Module | Default SKU / tier | Default size | Qty |
|---|---|---|---|---|
| PostgreSQL Flexible Server | database.bicep |
Standard_D2s_v3 / GeneralPurpose |
2 vCPU · 8 GiB RAM · 128 GiB storage | 1 |
| Azure Cache for Redis | cache.bicep |
Standard C1 | 1 GiB | 1 |
| ACA Environment | main.bicep |
Consumption workload profile | VNet-integrated | 1 |
| ACA App — pulp-api | containerapps.bicep |
Consumption | 1 vCPU · 2 GiB · min 1 / max 1 replica | 1 |
| ACA App — pulp-content | containerapps.bicep |
Consumption | 1 vCPU · 2 GiB · min 1 / max 1 replica | 1 |
| ACA App — pulp-worker | containerapps.bicep |
Consumption | 1 vCPU · 2 GiB · min 1 / max 1 replica | 1 |
| ACA Job — db-init | containerapps.bicep |
Consumption | 1 vCPU · 2 GiB · manual trigger | 1 |
| ACA Job — reconcile | containerapps.bicep |
Consumption | 1 vCPU · 2 GiB · manual trigger | 1 |
| Azure Files share | storage.bicep |
Standard_LRS · TransactionOptimized | 512 GiB quota | 1 |
| Blob Storage (3 containers) | storage.bicep |
Standard_LRS · Hot | pay-per-GB | 1 |
| Azure Container Registry | main.bicep |
Basic | — | 1 |
| Azure Service Bus | main.bicep |
Standard | 3 queues | 1 |
| Key Vault | keyvault.bicep |
Standard (RBAC) | — | 1 |
| Log Analytics Workspace | monitoring.bicep |
PerGB2018 | 30-day retention | 1 |
| Application Insights | monitoring.bicep |
Workspace-based | — | 1 |
| Virtual Network | network.bicep |
— | 10.40.0.0/16 · 4 subnets | 1 |
| Private DNS Zones | network.bicep |
— | 6 zones (postgres, blob, keyvault, redis, servicebus, acr) | 6 |
| User-Assigned Managed Identity | main.bicep |
— | — | 1 |
| NSG | network.bicep |
— | — | 1 |
No NAT gateway or standalone public IP is deployed. The ACA environment with
enablePublicValidation = true uses the ACA-managed public ingress IP (included in ACA pricing).
Azure Storage and Redis use public endpoints with CIDR/NSG restrictions in the default Milestone 1
configuration; private endpoints are wired via Private DNS zones but not yet activated for every
service in the shipped Bicep.
Three pricing scenarios¶
ACA Consumption pricing uses these list rates (East US, 2025): - vCPU: $0.000024 / vCPU-second - Memory: $0.000003 / GiB-second - Free monthly grant per subscription: 180,000 vCPU-seconds and 360,000 GiB-seconds
Jobs (db-init, reconcile) run once during bootstrap and infrequently thereafter; their cost is negligible and excluded from the monthly run-rate tables below.
Scenario 1 — Minimum / dev¶
Smallest viable SKUs for evaluation or CI. Cuts the database and Redis to burstable/basic.
| Resource | SKU | Monthly estimate (USD) |
|---|---|---|
| PostgreSQL Flexible Server | Burstable Standard_B2s · 32 GiB storage |
~$43 |
| Azure Cache for Redis | Basic C0 (256 MB) | ~$14 |
| ACA — 3 apps × 1 vCPU × 2 GiB (730 hr) | Consumption | ~$230 |
| Azure Files | Standard_LRS · TransactionOptimized · ~20 GiB used | ~$3 |
| Blob Storage | Standard_LRS · ~5 GiB | ~$1 |
| ACR | Basic | ~$5 |
| Service Bus | Standard | ~$10 |
| Key Vault | Standard | ~$1 |
| Log Analytics + App Insights | PerGB2018 · ~2 GiB/month | ~$0 (within free tier) |
| Private DNS (6 zones) | — | ~$3 |
| Bandwidth egress | ~2 GiB/month | ~$1 |
| Total | ≈ $311 / month |
⚠️ Basic Redis has no SLA and no replication. Suitable for dev/test only. Burstable B2s PostgreSQL will throttle under sustained CPU load (sync bursts).
Scenario 2 — Default quickstart (shipped .bicepparam)¶
Reflects the SKUs that deploy when you run az deployment group create with no param overrides.
This is what the repo tests against.
| Resource | SKU | Monthly estimate (USD) |
|---|---|---|
| PostgreSQL Flexible Server | GeneralPurpose Standard_D2s_v3 · 128 GiB storage |
~$164 |
| Azure Cache for Redis | Standard C1 (1 GiB) | ~$55 |
| ACA — 3 apps × 1 vCPU × 2 GiB (730 hr) | Consumption | ~$230 |
| Azure Files | Standard_LRS · TransactionOptimized · ~50 GiB used | ~$6 |
| Blob Storage | Standard_LRS · ~10 GiB | ~$2 |
| ACR | Basic | ~$5 |
| Service Bus | Standard | ~$10 |
| Key Vault | Standard | ~$1 |
| Log Analytics + App Insights | PerGB2018 · ~10 GiB/month | ~$23 |
| Private DNS (6 zones) | — | ~$3 |
| Bandwidth egress | ~5 GiB/month (on_demand sync + client downloads) | ~$1 |
| Total | ≈ $500 / month |
The ACA Consumption line dominates. Three always-on replicas (min=1) running 24×7 consume ~7.9 M vCPU-seconds and ~15.8 M GiB-seconds monthly after the free grant is deducted.
Scenario 3 — Production / hardened¶
Recommended sizing for a fleet of 50–500 nodes with scheduled syncs and HA requirements.
| Resource | SKU | Monthly estimate (USD) |
|---|---|---|
| PostgreSQL Flexible Server | GeneralPurpose Standard_D4s_v3 · Zone-redundant HA · 256 GiB |
~$460 |
| Azure Cache for Redis | Standard C2 (6 GiB) | ~$110 |
| ACA — 3 apps, min 1 / max 3 replicas with autoscale | Consumption | ~$350–$700 |
| Azure Files | Premium LRS · ~200 GiB | ~$41 |
| Blob Storage | Standard_LRS · ~50 GiB | ~$5 |
| ACR | Standard (geo-replication disabled) | ~$20 |
| Service Bus | Standard (consider Premium for VNet isolation) | ~$10–$680 |
| Key Vault | Standard | ~$2 |
| Log Analytics + App Insights | PerGB2018 · ~30 GiB/month | ~$69 |
| Private DNS (6 zones) | — | ~$3 |
| Bandwidth egress | ~20 GiB/month | ~$2 |
| Total (Service Bus Standard) | ≈ $1,070 – $1,410 / month | |
| Total (Service Bus Premium) | ≈ $1,740 – $2,090 / month |
Zone-redundant HA for PostgreSQL doubles the compute cost but provides 99.99% SLA and is required for IL5 workloads. Premium Azure Files halves latency on high-throughput package-blob writes.
Azure Government cost premium¶
Azure Government (MAG) pricing is typically 10–30% higher than Azure Commercial for the same SKUs. The premium varies by service:
| Service category | Typical premium |
|---|---|
| Compute (PostgreSQL, ACA) | 10–20% |
| Storage (Blob, Files) | 5–15% |
| Redis Cache | 10–25% |
| Networking / DNS | 5–10% |
| Log Analytics | 15–25% |
Apply ~20% blended uplift to the Commercial figures above for a rough Azure Government estimate.
Example: Default quickstart at ~$500/month Commercial → ~$600/month in MAG.
Quota and region considerations¶
- PostgreSQL Flexible Server quota is sometimes restricted on MSDN/Visual Studio subscriptions.
Per validated testing in this repo, eastus2 has exhibited quota rejections for PG Flex on MSDN
subs. Use
eastus(default in the example.bicepparam) or open a support ticket to increase quota before deploying. - Azure Government regions for Flex Server as of mid-2025:
usgovvirginia,usgovarizona. Check the MAG Products by Region page before deploying to a new region. - Redis Standard is available in all MAG regions. Redis Premium may require a quota increase.
- ACA Consumption is available in all current MAG regions.
Scaling guidance¶
When to upgrade the database SKU¶
| Signal | Recommended action |
|---|---|
pg_stat_activity shows >80% of max connections used |
Scale to Standard_D4s_v3 or add PgBouncer |
| Sync transactions taking >10 min with disk I/O wait >50% | Upgrade storage tier to Premium SSD or increase storageSizeGB |
pg_stat_statements shows sort/hash disk spills persisting after work_mem=65536 |
Scale compute to get more RAM; work_mem applies per sort node |
| Sustained CPU >70% for >2 hrs during sync | Move from Standard_D2s_v3 (2 vCPU) to Standard_D4s_v3 (4 vCPU) |
| Backup restore RTO >4 hr required | Enable zone-redundant HA; adds ~100% compute cost |
When to scale ACA replicas¶
The default is minReplicas: 1, maxReplicas: 1 for all three apps. This is sufficient for
a single-team mirror. Scale when:
pulp-contentHTTP 429 errors or p99 latency >2 s during peak clientapt updatewindows → increasemaxReplicasto 3–5 and add an HTTP-concurrency-based scale rule.pulp-workerfalls behind the sync queue (check Pulp task queue via/pulp/api/v3/tasks/) → increasepulp-workertominReplicas: 2for parallel task throughput.pulp-apiDjango response time >500 ms under operator load → scale API app or switch to a dedicated workload profile (D4 Dedicated) for predictable latency.
When to enable ACA autoscale¶
Add a scale rule to pulp-content and pulp-api keyed on HTTP concurrent requests:
scale: {
minReplicas: 1
maxReplicas: 5
rules: [
{
name: 'http-scale'
http: {
metadata: {
concurrentRequests: '20'
}
}
}
]
}
At 20 concurrent requests per replica × 5 replicas = 100 simultaneous apt clients before
additional scaling triggers. For fleets >500 nodes running apt update in rolling windows, consider
a dedicated workload profile (D4) for more predictable burst behaviour.
Azure Files vs Premium Files¶
The shipped default uses Standard_LRS TransactionOptimized for the pulp-media share.
If Pulp worker write throughput (blob cache population) becomes the bottleneck — visible as
NFS/SMB latency >20 ms or Azure Monitor Files latency metrics >10 ms — migrate to
Premium_LRS (FileStorage kind). Premium Files charges ~$0.21/GiB-month provisioned vs.
~$0.06/GiB-month used for Standard, so size the share tightly.