Appearance
Cost governance ​
Audience: platform team, platform owner Related ADO epic: AB#3074 (Build Platform), AB#3182 (Foundation documentation — operations layer, S4) Last updated: 2026-06-18
Governing constraint — free or low-cost until Microsoft nonprofit status; then free or low-cost under Azure where possible ​
Every service choice in Heritage Community Hub is evaluated against this constraint before adoption: use free or near-zero-cost solutions until Microsoft Nonprofits credits are approved; after credits are granted, prefer free or low-cost services under the Azure umbrella where possible.
This constraint is not a hint — it drives concrete architecture choices (Cloudflare R2 over Azure Blob for media egress, Postgres burstable tier over premium, Container Apps consumption over dedicated). Any service that cannot meet the free/cheap bar without nonprofit credits requires explicit owner approval, documented in the relevant ADR.
The governing cost constraint is recorded in the platform strategy and referenced in ADR 0024 (portability), ADR 0010 (media storage), and ADR 0013 (SMS/notifications).
Cost model by service ​
Azure Container Apps — consumption plan ​
The platform API runs as a Docker container on Azure Container Apps (ADR 0024). The consumption plan charges per vCore-second and GiB-second of actual execution, with a free monthly grant:
| Meter | Free monthly grant | Rate above free grant |
|---|---|---|
| vCPU time | 180,000 vCPU-seconds | ~$0.000024/vCPU-second |
| Memory time | 360,000 GiB-seconds | ~$0.000003/GiB-second |
| Requests | 2 million requests | ~$0.40/million |
At ~100–200 members with light API traffic (member logins, calendar reads, announcement delivery, media playback signed-URL requests), the community will almost certainly remain within the free monthly grant throughout the period before nonprofit credits. There is no charge for idle time on the consumption plan.
Validation required before Phase 1 provisioning: confirm the Container Apps consumption free tier ceiling against expected traffic patterns. This was identified as a risk in ADR 0024 — the prior Azure Functions Consumption 1 million free executions/month is a well-known ceiling; the Container Apps equivalent requires verification under a Phase 1 infrastructure research task (AB#3074).
Estimated monthly cost at community scale: $0 during pre-credit period (within free grant); remains near $0 under nonprofit credits.
Azure DB for PostgreSQL Flexible Server — burstable tier ​
The platform database is Postgres on Azure Database for PostgreSQL Flexible Server (ADR 0024, superseding the ADR 0004 Azure SQL Serverless choice).
The burstable tier (B1ms — 1 vCore, 2 GiB RAM) is the correct starting point for a ~200-member community with a low-traffic workload:
| Component | Estimated monthly cost |
|---|---|
| Compute — B1ms (burstable) | ~$12–15/month |
| Storage — 32 GiB provisioned minimum | ~$3–4/month |
| Backups (7-day default retention) | Included up to provisioned storage size |
| Total estimate | ~$15–20/month |
The B1ms tier can handle infrequent, short bursts of database activity. It does not autopause on idle in the same way as Azure SQL Serverless; there is a baseline compute charge even when the database is idle. Under Microsoft Nonprofits Azure credits (~$3,500/year), this cost is covered.
Scale trigger: move to the next tier (B2ms or General Purpose) only when observed CPU credits are consistently exhausted at peak — not proactively.
Storage — Cloudflare R2 ​
Media storage (sermons, music, audio) uses Cloudflare R2 as the preferred object store under the StorageProvider abstraction defined in ADR 0010. R2 was chosen specifically because it charges zero egress fees — media playback via signed URLs pulls bytes from R2 to the member's browser or device without any per-byte transfer charge.
| Meter | Rate |
|---|---|
| Storage | ~$0.015/GB/month |
| Class A operations (write/list) | $4.50/million requests |
| Class B operations (read/GET) | $0.36/million requests |
| Egress to internet | $0.00/GB |
Estimates for sermons and music media library:
| Library size | Storage cost/month |
|---|---|
| 50 sermons × 500 MB avg | 25 GB → ~$0.38/month |
| 200 sermons × 500 MB avg | 100 GB → ~$1.50/month |
| 500 sermons × 500 MB avg | 250 GB → ~$3.75/month |
Egress cost for any of these scenarios is $0 regardless of playback frequency, which is the primary reason R2 was chosen over Azure Blob Storage (see Cost optimisation decisions).
The StorageProvider interface (ADR 0010) means the concrete storage backend can be swapped by updating one adapter module. No client-facing contract or RBAC logic changes.
Note on Cloudflare R2 and nonprofit credits: R2 is a Cloudflare service, not Azure. It is billed to a Cloudflare account and is not covered by Microsoft Nonprofits credits. However, at the storage rates above, the absolute monthly cost is low enough that this is acceptable. If nonprofit credits grow the Azure budget materially and the team prefers consolidation, the StorageProvider adapter can be switched to Azure Blob Storage (Cool tier) with egress mitigated by Azure CDN.
SMS — Twilio ​
Short Message Service (SMS) delivery is handled by Twilio, accessed through the platform's provider-neutral SmsProvider adapter (ADR 0013). SMS is the only channel in the notification transport that has a per-message recurring cost.
Pricing components:
| Component | Rate |
|---|---|
| Per outbound segment (US) | ~$0.0083/segment |
| Local long-code number rental | ~$1.15/month |
| A2P 10DLC registration — brand | one-time ~$4.00 |
| A2P 10DLC registration — campaign | one-time ~$15.00 |
| A2P 10DLC monthly campaign fee | ~$10.00/month |
| Carrier pass-through surcharge | variable; ~$0.003–0.005/segment (US) |
Application-to-Person (A2P) 10DLC (10-digit long code) registration is a US carrier requirement for any business or organization sending SMS at volume. It applies to all providers, not just Twilio; it is not a Twilio-specific fee.
Monthly cost estimate at community scale:
Assume ~150 adult members (excluding children, who receive no SMS — ADR 0007), 3 notifications per week:
150 members × 3 notifications × 4.3 weeks = ~1,935 SMS/month
~1,935 × $0.0083 + $1.15 number + $10 A2P monthly fee ≈ ~$27/month
(before carrier pass-through surcharges of ~$6–10/month)
Total estimate with surcharges: ~$33–37/monthThis was accepted by the owner (2026-06-18) as a modest ministry operating expense. The SmsProvider adapter makes Telnyx a config-only swap if volume grows; Telnyx per-segment pricing (~$0.0040) would reduce the message cost to approximately half.
Cost-control levers:
- Members may opt out of non-urgent SMS (priority 0 notifications); urgent notifications (priority 2 — safety, weather cancellations) always send.
- Set a Twilio spending alert and monthly cap in the Twilio console.
- The announcement approval workflow (ADR 0023) gates what reaches fan-out; no message sends without an approver's explicit action.
Email — SendGrid ​
Outbound email is handled by SendGrid, accessed through the platform's provider-neutral EmailProvider adapter (ADR 0013).
Free tier limits:
| Tier | Emails/day | Monthly equivalent | Cost |
|---|---|---|---|
| Free (Essentials) | 100 emails/day | ~3,000/month | $0 |
At ~150–200 adult members receiving ~12–15 email notifications per month (3/week), expected volume is approximately 1,800–3,000 emails per month — at or just within the free daily limit. No cost is expected at congregation scale during the pre-nonprofit period.
Paid tier trigger: if notification volume routinely reaches 100 emails per day, evaluate the SendGrid Essentials paid tier ($19.95/month for 50,000 emails). The EmailProvider adapter means an alternative (Mailgun, Resend, or Azure Communication Services Email under nonprofit credits) can be wired in hours if SendGrid policies or limits become a constraint.
Free tier risks: SendGrid free accounts are subject to usage and anti-abuse policies. A spike in bounce rates or a spam complaint can suspend delivery. Monitor bounce rates and complaint rates through SendGrid event webhooks forwarded to Application Insights (ADR 0005).
Clerk — identity provider ​
Clerk is the authentication provider (ADR 0003) for all adult member sign-ins (Apple and Google social login).
| Tier | MAU (Monthly Active Users) limit | Cost |
|---|---|---|
| Free (Hobby) | 10,000 MAU | $0 |
| Pro | unlimited | $25/month base + $0.02/MAU above 10,000 |
A congregation of ~100–200 adults will remain comfortably within the 10,000 MAU free tier. The paid tier does not apply until the community exceeds 10,000 active users.
Note: children use parent-managed credentials stored in the platform's own Users table (ADR 0007, ADR 0003), not Clerk. Child credentials do not count against Clerk's MAU limit.
Cost monitoring ​
Azure Cost Management is the primary tool for tracking Azure spend (Container Apps, Postgres, Blob/CDN if used, Key Vault operations).
Required configuration before Phase 1 infrastructure goes live (AB#3074):
- Budget alert: create a monthly budget in Azure Cost Management scoped to the Heritage Community Hub resource group. Set an alert threshold at 80% and 100% of the monthly budget. Route alerts to the platform owner email and an ADO notification channel.
- Zero-spend alert: add an anomaly alert to detect unexpected spend spikes (e.g., accidental resource creation or a misconfigured egress path).
- Monthly review cadence: review the Cost Management breakdown on the first Monday of each month. Compare actuals against the estimates in this document and update the estimates if actuals diverge by more than 25%.
- Twilio spending cap: set a monthly spending limit in the Twilio console to prevent SMS cost runaway from a misconfigured fan-out or a compromised notification queue (ADR 0013 risk).
Non-Azure services (Twilio, Clerk, SendGrid, Cloudflare R2) are monitored through their respective console dashboards. Add the platform owner email to billing alerts in each console.
Nonprofit status ​
Microsoft Nonprofits program offers eligible 501(c)(3) organizations approximately $3,500/year in Azure credits. Heritage Virginia pursuing nonprofit status is a prerequisite.
Upon approval:
- Priority services to move under credit: Azure DB for PostgreSQL Flexible Server compute (~$15/month) and Azure Container Apps consumption (estimated near $0 but confirmed under credit). These are the two Azure services with meaningful recurring charges at community scale.
- Key Vault operations and Azure Monitor / Application Insights (~5 GB/month free each) are expected to remain within their always-free or free-tier limits regardless of credit status.
- Azure Static Web Apps Free (web shell hosting — ADR 0004) has no cost at the free tier.
- R2, Twilio, SendGrid, and Clerk are third-party services and are not covered by Microsoft Nonprofits credits. Their costs continue as described in the sections above.
Action: open the nonprofit application at nonprofits.microsoft.com early — the review process takes several weeks. The application requires proof of 501(c)(3) status. Until credits are granted, the working assumption is that Azure DB for PostgreSQL Flexible Server is the only service with a non-trivial recurring Azure cost (~$15–20/month).
Cost optimisation decisions ​
The following architectural choices were made explicitly on cost grounds and are locked in the indicated ADRs. They are recorded here so the rationale is visible in one place.
| Decision | What was chosen | What was rejected | Cost rationale | ADR |
|---|---|---|---|---|
| Object storage for media | Cloudflare R2 (zero egress) | Azure Blob Storage Hot tier (~$0.087/GB egress) | A medium sermon library (100 GB) streamed to 200 members would generate material egress cost on Blob; R2 eliminates it entirely at comparable storage rates | ADR 0010 |
| API compute | Azure Container Apps (consumption plan; no charge at idle) | Azure Functions Consumption (1 M executions/month free) | Both are effectively free at congregation scale; Container Apps was chosen for portability (no Functions host bindings) — cost is neutral, not worse | ADR 0024 |
| Database engine | Postgres on Flexible Server burstable (B1ms) | Azure SQL Serverless (T-SQL, General Purpose) | Postgres is portable (identical dialect on AWS RDS, GCP Cloud SQL, Supabase) and comparable in cost at the burstable tier; choosing Postgres now avoids a schema migration later | ADR 0024 |
| SMS provider | Twilio (provider-neutral adapter; Telnyx as cost-down swap) | Azure Communication Services SMS (~$0.0075/segment + Azure-locked) | ACS is Azure-locked, contradicting the portability posture (ADR 0024); the ~$8/month difference between Twilio and Telnyx is immaterial at congregation scale but Telnyx is documented as the config-only swap if volume grows | ADR 0013 |
| Email provider | SendGrid free tier (provider-neutral adapter) | Azure Communication Services Email | SendGrid free tier covers expected volume at no cost; ACS Email would introduce Azure lock-in in the communications layer | ADR 0013 |
| Auth provider | Clerk free tier (10,000 MAU) | Azure AD B2C (~$0.0016/MAU above 50,000 free) | Clerk free tier covers a faith community of any realistic size; no Azure lock-in for end-user identity; Entra stays for infrastructure identity only | ADR 0003 |
| Video transcoding | None — original format only | Azure Media Services (~$50–200+/month minimum) | No adaptive bitrate requirement at this community size; no cost justified for transcoding pipeline | ADR 0010 |
Related ADRs ​
| ADR | Relevance |
|---|---|
| ADR 0003 — Authentication: Clerk + Apple/Google | Clerk free tier; no Entra for end users |
| ADR 0004 — Cloud/hosting stack, CI/CD, and free-tier path | Azure SWA Free, Key Vault, GitHub Actions CI/CD (free for public repos) |
| ADR 0005 — Observability model | Application Insights + Log Analytics free tier (~5 GB/month) |
| ADR 0010 — Sermons & Music Hub | StorageProvider abstraction; R2 zero-egress rationale; egress cost revisit triggers |
| ADR 0013 — Notification transport | Twilio SMS cost estimate; SendGrid free tier; provider-neutral adapters; A2P 10DLC fees |
| ADR 0024 — Cloud portability & provider abstraction | Container Apps consumption plan; Postgres Flexible Server burstable tier; portability vs cost trade-offs |