+ {/* Worker CPU time runs ~20x tighter than wall-clock latency,
+ hence the dedicated "cpu" budget. */}
+
))}
diff --git a/apps/web/src/components/infra/cloudflare/cloudflare-zone-table.tsx b/apps/web/src/components/infra/cloudflare/cloudflare-zone-table.tsx
index 5f86cc94c..d89487b66 100644
--- a/apps/web/src/components/infra/cloudflare/cloudflare-zone-table.tsx
+++ b/apps/web/src/components/infra/cloudflare/cloudflare-zone-table.tsx
@@ -1,6 +1,7 @@
import { Link } from "@tanstack/react-router"
import { Skeleton } from "@maple/ui/components/ui/skeleton"
+import { LatencyValue } from "@maple/ui/components/latency-value"
import type { CloudflareZoneRow } from "@/api/warehouse/cloudflare-infra"
import { formatLatency, formatNumber } from "@/lib/format"
@@ -193,12 +194,29 @@ export function CloudflareZoneTable({ zones, waiting }: CloudflareZoneTableProps
- {formatOptionalLatency(zone.ttfbP50Ms)}
+
+
- {numCell(formatOptionalLatency(zone.ttfbP99Ms))}
-
- {formatOptionalLatency(zone.originP99Ms)}
+
+
+
+
+
))}
diff --git a/apps/web/src/components/infra/planetscale/planetscale-top-queries.tsx b/apps/web/src/components/infra/planetscale/planetscale-top-queries.tsx
index 6b0cada7d..4ed69a7da 100644
--- a/apps/web/src/components/infra/planetscale/planetscale-top-queries.tsx
+++ b/apps/web/src/components/infra/planetscale/planetscale-top-queries.tsx
@@ -2,11 +2,12 @@ import { useMemo } from "react"
import { Skeleton } from "@maple/ui/components/ui/skeleton"
import { cn } from "@maple/ui/lib/utils"
+import { LatencyValue } from "@maple/ui/components/latency-value"
import { Result } from "@/lib/effect-atom"
import { useRefreshableAtomValue } from "@/hooks/use-refreshable-atom-value"
import { planetscaleQueryInsightsResultAtom } from "@/lib/services/atoms/warehouse-query-atoms"
-import { formatLatency, formatNumber, formatRelativeTime } from "@/lib/format"
+import { formatNumber, formatRelativeTime } from "@/lib/format"
/** Warehouse "YYYY-MM-DD HH:mm:ss" → epoch ms (values are UTC). */
const warehouseTimeToMs = (value: string): number => new Date(`${value.replace(" ", "T")}Z`).getTime()
@@ -90,14 +91,12 @@ export function PlanetScaleTopQueries({
+ {formatNumber(row.queryCount)} calls
- {formatNumber(row.queryCount)} calls
+ p50
- p50 {formatLatency(row.p50LatencyMillis)}
-
-
- p99 {formatLatency(row.p99LatencyMillis)}
+ p99
{formatNumber(row.rowsReadPerQuery)} rows read/query
diff --git a/apps/web/src/components/service-map/service-map-node.tsx b/apps/web/src/components/service-map/service-map-node.tsx
index 4d03a8bf3..87412cbb7 100644
--- a/apps/web/src/components/service-map/service-map-node.tsx
+++ b/apps/web/src/components/service-map/service-map-node.tsx
@@ -1,6 +1,7 @@
import { memo } from "react"
import { Handle, Position } from "@xyflow/react"
import { cn } from "@maple/ui/utils"
+import { latencyToneClass } from "@maple/ui/lib/latency-tone"
import { Tooltip, TooltipTrigger, TooltipContent } from "@maple/ui/components/ui/tooltip"
import {
AwsLambdaIcon,
@@ -132,8 +133,16 @@ const Handles = () => (
* infrastructure dependencies stand out from application services on the map.
*/
function DatabaseNode({ data }: { data: ServiceNodeData }) {
- const { throughput, errorRate, avgLatencyMs, p95LatencyMs, dbSystem, dbNamespace, selected, planetscale } =
- data
+ const {
+ throughput,
+ errorRate,
+ avgLatencyMs,
+ p95LatencyMs,
+ dbSystem,
+ dbNamespace,
+ selected,
+ planetscale,
+ } = data
// Named databases show their identity as the title; the system name takes over
// the small badge slot (the generic node keeps the coarse category). Databases
// behind Cloudflare Hyperdrive collapse to a single "Hyperdrive"-branded node;
@@ -192,8 +201,16 @@ function DatabaseNode({ data }: { data: ServiceNodeData }) {
value={`${(errorRate * 100).toFixed(1)}%`}
valueClassName={errorRateClass(errorRate)}
/>
-
-
+
+
{/* PlanetScale live health (scraped branch metrics, window rollup) */}
@@ -322,7 +339,11 @@ function ServiceNode({ data }: { data: ServiceNodeData }) {
valueClassName={errorRateClass(errorRate)}
/>
-
+
{/* Pods badge — empty placeholder when no infra so widths stay stable */}
@@ -406,7 +427,11 @@ function NamespaceAggregateNode({ data }: { data: ServiceNodeData }) {
value={`${(errorRate * 100).toFixed(1)}%`}
valueClassName={errorRateClass(errorRate)}
/>
-
+