Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/plans/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
84 changes: 84 additions & 0 deletions docs/plans/mystira-r13-runway-performance-decision.md
Original file line number Diff line number Diff line change
@@ -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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Correct the future-dated cost window

This note was committed/generated on 2026-07-13 at 01:42 UTC, but the evidence range claims actual costs through 2026-07-13T23:59:59Z. In that context the final day can only be partial, so the table below can be read as complete actual monthly spend even though the stated window includes hours that had not occurred yet; please either end the range at the query time/last complete day or label the July 13 data as partial.

Useful? React with 👍 / 👎.

- **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/<subscription-id>/providers/Microsoft.CostManagement/query?api-version=2023-11-01" --body "@C:\tmp\mystira-cost-query-resource.json"
az monitor metrics list --resource "<resource-id>" --metric "<metric-list>" --interval PT1H --aggregation Average --start-time "<start>" --end-time "<end>"
```
Loading