diff --git a/docs/plans/README.md b/docs/plans/README.md index 43f123f..f766dd5 100644 --- a/docs/plans/README.md +++ b/docs/plans/README.md @@ -12,6 +12,7 @@ ## MVP launch and funding - [NeuralLiquid MVP funding portfolio](./neuralliquid-mvp-funding-portfolio.md) +- [Mystira R13 runway / performance decision](./mystira-r13-runway-performance-decision.md) - [OmniPost MVP-to-live](./omnipost-mvp-to-live.md) - [ConvoLens MVP-to-live](./convolens-mvp-to-live.md) - [Cognitive Mesh MVP-to-live](./cognitive-mesh-mvp-to-live.md) diff --git a/docs/plans/mystira-r13-runway-performance-decision.md b/docs/plans/mystira-r13-runway-performance-decision.md new file mode 100644 index 0000000..33eb966 --- /dev/null +++ b/docs/plans/mystira-r13-runway-performance-decision.md @@ -0,0 +1,84 @@ +# Mystira R13 Runway / Performance Decision Note + +**Generated:** 2026-07-13 +**Scope:** Mystira Azure spend and R13 performance options raised in the 2026-07-12/13 field notes. +**Baton task:** `3fdf93a8-5657-493d-b1e8-5670d91bb16f` + +## Evidence Classification + +- **Actual cost data:** Azure Cost Management API, subscription `bb4e3882-2079-4bab-8974-611bc0b8bb58`, period `2026-06-13T00:00:00Z` to `2026-07-13T23:59:59Z`, currency USD. +- **Actual utilization data:** Azure Monitor metrics, 14-day window ending 2026-07-13, hourly average aggregation. +- **Estimate / pricing caveat:** Azure public pricing pages are estimate guidance only; actual billing is governed by agreement, date, currency, and exchange rate. Use actual Cost Management data for runway decisions. + +## Current Monthly Cost Drivers + +| Area | Actual cost | Evidence | Decision relevance | +| --- | ---: | --- | --- | +| Mystira/global App Service plans | `$366.15` | `mys-global-shared-rg / Azure App Service` | Primary App Service spend. Includes `mys-global-shared-asp` (`P1v3`), `mys-prod-emergency-app-asp` (`P1v3`), and `mys-prod-emergency-admin-asp` (`S1`). | +| Prod Postgres | `$214.84` | `mys-prod-core-rg / Azure Database for PostgreSQL`, resource `mys-prod-core-db` | Cleanest immediate savings candidate based on low utilization. | +| Prod Service Bus | `$264.25` | `mys-prod-core-rg / Service Bus`, resource `mysprodcoresb` | Not in the field note, but material to runway; review tier/namespace need separately. | +| Prod Front Door | `$30.77` | `mys-prod-app-rg / Azure Front Door Service`, resource `mys-prod-app-afd` | Already active. The proposed "Front Door + Redis" option should be reframed as Redis on top of existing Front Door. | +| Prod identity Container Apps | `$48.16` | `mys-prod-identity-rg / Azure Container Apps` | Modest compared with App Service/Postgres/Service Bus. | +| Redis | `$0.00` | `az redis list` returned no caches | Redis is not currently deployed. Any Redis option is incremental cost and implementation work. | + +## Utilization Snapshot + +| Resource | SKU / shape | 14-day average | 14-day max | Reading | +| --- | --- | ---: | ---: | --- | +| `mys-global-shared-asp` | App Service `P1v3`, 1 worker | CPU `13.82%`, memory `78.69%` | CPU `30.40%`, memory `87.93%` | CPU has headroom, but memory is high enough that down-tiering the main shared App Service plan is risky without app-level memory profiling. | +| `mys-prod-core-db` | PostgreSQL Flexible Server `Standard_B2ms`, 128 GB | CPU `7.41%`, memory `19.19%`, storage `7.14%` | CPU `9.04%`, memory `20.77%`, storage `7.14%` | Strong down-tier candidate. Current database appears materially overprovisioned for observed load. | + +## Decision + +1. **Do not down-tier the main shared App Service plan during R13 without a memory investigation.** + The field note is correct that account creation and parental consent became faster after the App Service bump. CPU is not the pressure point, but memory is already around `79%` average and `88%` max. A direct downgrade risks reintroducing latency or restarts. + +2. **Pilot Postgres down-tier first, with rollback.** + `mys-prod-core-db` is the cleanest immediate savings lever. Actual cost is `$214.84` for the period, while utilization is low. A controlled downgrade could plausibly recover most of the field-note `$200` saving, but only if connection/latency checks stay healthy. + +3. **Treat Redis as a performance feature, not a cost replacement.** + Front Door is already active at `$30.77`. Redis is absent, so activating Redis adds cost and operational surface. Add it only for a concrete cache target such as auth/session hot paths, catalog reads, or profile/consent read-through cache, with hit-rate telemetry. + +4. **Review Service Bus before deeper App Service cuts.** + Service Bus at `$264.25` is a larger monthly driver than prod Postgres and was not in the field note. Before spending a week on Azure Functions offload or dynamic scaling, inspect namespace tier, queues/topics, and whether the current SKU is required. + +5. **Defer dynamic scaler / Azure Functions offload unless runway requires engineering spend.** + Dynamic plan switching creates an interruption risk during load. Azure Functions offload is likely a multi-day to week-plus refactor. Neither should be first unless the Postgres/Service Bus review is insufficient. + +## Safe Next Actions + +1. **Postgres controlled down-tier plan** + - Capture baseline: API health, account creation, parental consent, first-story start, p95/p99 latency, DB CPU/memory/storage/connections. + - Down-tier `mys-prod-core-db` one step in a low-traffic window. + - Watch the same metrics for 24 hours. + - Roll back immediately if memory, connection failures, or p95/p99 latency regresses. + +2. **Service Bus cost review** + - Identify current namespace SKU and feature usage. + - Confirm whether Topics, sessions, duplicate detection, or throughput requirements force the current tier. + - If not, create a lower-tier migration plan with message-drain and rollback. + +3. **App Service memory investigation** + - Break down memory by hosted apps sharing `mys-global-shared-asp`. + - Check whether staging slots, admin/story/app APIs, or background tasks dominate memory. + - Only consider App Service down-tier after memory falls below a sustained safe ceiling. + +4. **Redis gate** + - Do not add Redis until there is a named cache target, expected hit rate, invalidation plan, and cost ceiling. + - If used, start small and measure latency delta before increasing tier. + +## Funding / Runway Impact + +- The field-note estimate that Mystira is near `$1k/month` is plausible from actual Azure data once App Service, Postgres, Service Bus, Front Door, identity Container Apps, monitoring, and supporting services are included. +- The immediate low-risk savings path is **Postgres down-tier + Service Bus review**, not App Service down-tier. +- The performance-preserving path is to keep the current App Service tier for R13 while reducing database/messaging waste and adding cache only if it has measured benefit. + +## Evidence Commands + +```powershell +az appservice plan list --query "[].{name:name,resourceGroup:resourceGroup,sku:sku.name,tier:sku.tier,capacity:sku.capacity,numberOfWorkers:numberOfWorkers,kind:kind,location:location,id:id}" -o json +az postgres flexible-server list --query "[].{name:name,resourceGroup:resourceGroup,sku:sku.name,tier:sku.tier,version:version,storageGb:storage.storageSizeGb,location:location,state:state,id:id}" -o json +az redis list --query "[].{name:name,resourceGroup:resourceGroup,sku:sku.name,family:sku.family,capacity:sku.capacity,location:location,provisioningState:provisioningState,id:id}" -o json +az rest --method post --url "https://management.azure.com/subscriptions//providers/Microsoft.CostManagement/query?api-version=2023-11-01" --body "@C:\tmp\mystira-cost-query-resource.json" +az monitor metrics list --resource "" --metric "" --interval PT1H --aggregation Average --start-time "" --end-time "" +```