Subchapter 25.9
references/design-refs/fast-path.mdMarkdown10 KBView on GitHub
The lookup DATA lives in knowledge/design/fast-path-services.json, loaded via the
design phase’s _knowledge. This file is the CONTRACT: what the table means, what
may go in it, how it is applied, and what the labels are allowed to claim.
Do not restate rows from the JSON here. One canonical copy — see SKILL.md § Context Loading Rules, “No duplication”.
A row belongs in Direct Mappings when, and only when:
Is this target correct regardless of the surrounding architecture?
This is a sharper test than “is it 1:1?”, and it follows directly from the invariant
in design.md: a pattern may narrow rubric candidates and may never change a
deterministic mapping’s target. If a pattern could ever want a different target for
a row, the row is not architecture-invariant and does not belong in the table.
Three consequences worth stating, because each one looks like an exception and is not:
enabled_protocol; the Event Hubs row reads kafka_enabled; the
Cosmos row reads the API. Each reads a property of the resource itself, not of its
neighbours, so the target is still fixed once the resource is known. This is the
same shape as gcp’s google_sql_database_instance (SQL Server) row, which is
conditioned on the engine. Owner decisions 11.4 and 11.5 state that protocol is the
whole rubric for those two, which means there is no rubric left — only a lookup.aws_service is unchanged, so the
label holds. Only a substituted service would break the invariant.Always condition. gp3-versus-io2
by IOPS, and instance size from measured utilization, happen after the service is
chosen. The row picks the service; sizing never revisits it.No compute in the table, with one exception. Microsoft.Web/serverfarms,
Microsoft.Compute/virtualMachines, and Microsoft.Web/sites (kind=functionapp)
are all rubric decisions — a function inside an otherwise Fargate-based workload may
belong on Fargate, and a durable or long-running function hits an eliminator anyway.
Microsoft.ContainerService/managedClusters → EKS is the exception because a team
already running Kubernetes does not stop running Kubernetes; the target is invariant
in a way the others are not.
The plan’s §7a.3 fixed a 10-row table before the canonical child-type vocabulary existed. Four rows are additions of necessity rather than scope:
| Added row | Why it is not optional |
|---|---|
Microsoft.Network/virtualNetworks/subnets | Canonicalization emits subnets as their own child-typed resources. Without a row, every subnet reaches the unknown-type policy, matches “sits in a network provider namespace”, and STOPs the design — on every real estate. |
.../blobServices/containers, .../queueServices/queues, .../tableServices/tables | Same reason, and each has an unambiguous target (S3, SQS, DynamoDB). Leaving them out would STOP on any account that declares its containers explicitly. |
Decision 11.5 was recorded as disturbing the Microsoft.Storage/storageAccounts → S3 Always row. It does not, and the reason is worth writing down so it is not
re-litigated: canonicalization already makes a file share its own resource.
azurerm_storage_share translates to
Microsoft.Storage/storageAccounts/fileServices/shares and appears as a separate
resources[] entry, so a share is never inside the account’s mapping unit and cannot
pull the account’s target anywhere.
So the account row keeps Always → S3 for its blob surface, the share is its own
protocol-conditioned row, and the only condition the account row needs is the case
where the account has no blob surface at all (account_kind: FileStorage). Children
never inherit the parent’s target.
Four tiers. Use them only as defined here — they describe how the mapping was chosen, never how obvious the answer feels.
JSON confidence | Means | Say this to users |
|---|---|---|
deterministic | The canonical ARM type matched a Direct Mappings row, the row’s condition held, and the target came from that row. No rubric was run. | Standard pairing |
measured | A rubric outcome backed by observed utilization, not declared config — RDfA’s rollup or az monitor metrics list. Must cite the evidence. | Measured from your actual usage |
inferred | A rubric outcome from declared configuration only. | Tailored to your setup |
billing_inferred | The billing-only design path — spend line items without infrastructure detail. | Estimated from billing only |
measured is named after the evidence rather than the tool (it was rdfa_inferred in
an earlier draft) precisely so the live az path can earn it when it supplies the same
metrics.
Two labels that are not confidence values. A specialist gate writes
Deferred — specialist engagement into deferred[] and carries no confidence
field — it did not come from a rubric, and writing inferred on a deferral would claim
reasoning that did not happen. A Skip Mapping produces no entry at all, only a
warnings[] record.
Canonical reference: this section. Other phase files point here rather than restating it.
The common confusion: design-refs/index.md lists a typical AWS target per ARM
type. That is not the same as deterministic. Confidence is deterministic only when
the type appears in fast-path-services.json → direct_mappings and its condition
held; everything else routed through index.md is inferred (or measured when
utilization backed it).
Per resource, in this order. Stop at the first match.
skip_mappings → no target. Write a warnings[] entry with the reason. If the
row’s kind is config_source, read its contribution FIRST and name what it
contributed in the warning. Never route a skip through the rubric, and never
through the unknown-type STOP.specialist_gates → a deferred[] entry with aws_service: "Deferred — specialist engagement" and the row’s reason. Check conditional gates
(the #sql_on_vm form) against config, not just the type.direct_mappings → evaluate condition; if it fails, try alternatives[] in
order; if one holds, assign that aws_service with confidence: deterministic.
If a row carries route_to_rubric and its condition holds, fall through to step 5
instead. Run no rubric for a matched row.index.md → category rubric file → pattern constraint → six criteria.phases/design/design-infra.md.Independently of the above, check every mapped resource against hard_blockers. A
blocker does not change the target; it adds a warnings[] entry with
severity: "blocker". It is a statement, not a question — presenting it as a choice
would imply one of the answers works.
Applied after selection, and only to rubric outcomes. Never to a deterministic
row: substituting a preferred target over a fast-path row is the invariant violation
this whole file exists to prevent.
| Workload category | Preferred target | Rationale |
|---|---|---|
| PaaS / managed platform (App Service) | Elastic Beanstalk, unless preferences.json selects containers or EKS | Preserves the managed-platform model the customer already pays for |
| Containerized workloads | Fargate (default), Lambda (event-driven), EKS (Kubernetes already in use) | Deeper VPC / ALB / IAM / scaling integration than lighter-weight alternatives |
| Third-party auth in use | Keep the existing provider | A startup on Entra External ID, Auth0, or Clerk should not be moved to Cognito |
AWS App Runner is not a candidate anywhere, at any step, including as a
“forward-look” — it stopped accepting new customers in April 2026. ECS Express Mode
may be mentioned only as a forward-look on the Fargate override path. A _postcondition
on the design phase asserts App Runner appears nowhere in aws-design.json; that
assert has no mechanical teeth, so the real enforcement is here.