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
221 changes: 221 additions & 0 deletions app/scaling/fixtures/synthetic.v2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
{
"schemaVersion": 2,
"network": "synthetic-testnet",
"collectedAt": "2026-01-02T00:00:00Z",
"context": "Synthetic fixture: every number is invented to exercise the schema. Not a measurement of any network.",
"windows": {
"day": { "label": "24 h", "start": "2026-01-01T00:00:00Z", "end": "2026-01-02T00:00:00Z" },
"week": { "label": "7 d", "start": "2025-12-26T00:00:00Z", "end": "2026-01-02T00:00:00Z" }
},
"ladder": {
"observed": {
"p50": {
"value": 12.5,
"unit": "Mgas/s",
"tag": "measured",
"window": "day",
"source": { "label": "Synthetic dashboard", "url": "https://example.com/synthetic/gas-per-second" },
"help": "Median gas executed per second over the window."
},
"p99": {
"value": null,
"unit": "Mgas/s",
"tag": "not-measured",
"window": null,
"help": "Peak gas per second over the window; needs a p99 query."
}
},
"operatingPoint": {
"value": 40,
"unit": "Mgas/s",
"tag": "measured",
"window": null,
"help": "Fee-market target: gas target divided by elasticity. Where fees start rising."
},
"configuredLimit": {
"value": 200,
"unit": "Mgas/s",
"tag": "measured",
"window": null,
"help": "Block gas limit divided by block time. A setting, not demonstrated capacity."
},
"qualified": {
"value": null,
"unit": "Mgas/s",
"tag": "not-established",
"window": null,
"help": "Highest rate a full-block run on mainnet-sized state has sustained. No run exists yet."
}
},
"ceilings": [
{
"area": "da",
"value": 95,
"unit": "Mgas/s",
"tag": "modeled",
"formula": "(blob_target × blob_bytes ÷ 12 s) × 0.8 ÷ da_bytes_per_gas",
"inputs": [
{ "name": "blob_target", "value": 6, "unit": "blobs/block", "asOf": "2026-01-01T00:00:00Z", "status": "configured" },
{ "name": "blob_bytes", "value": 131072, "unit": "bytes", "asOf": "2026-01-01T00:00:00Z", "status": "configured" },
{
"name": "da_bytes_per_gas",
"value": 0.0055,
"unit": "bytes/gas",
"asOf": "2026-01-02T00:00:00Z",
"source": { "label": "Synthetic query", "url": "https://example.com/synthetic/da-bytes-per-gas" },
"status": "observed"
}
],
"help": "Gas per second the data-availability layer absorbs at 80% blob utilization."
},
{
"area": "execution",
"value": 150,
"unit": "Mgas/s",
"tag": "estimated",
"formula": "sequencer gas/s of the newest passing bench run",
"inputs": [
{ "name": "bench_run", "value": "synthetic-run-1", "unit": "", "asOf": "2025-12-20T00:00:00Z", "status": "observed" },
{ "name": "state_size", "value": null, "unit": "GB", "asOf": null, "status": "pending" }
],
"reason": "state size not recorded for the run",
"help": "Highest rate at which block building fits the slot and validators keep up, on mature state."
},
{
"area": "state",
"value": null,
"unit": "Mgas/s",
"tag": "not-modeled",
"formula": "state_growth_budget ÷ state_bytes_per_gas",
"inputs": [
{ "name": "single_node_max", "value": 45, "unit": "TB", "asOf": "2026-01-01T00:00:00Z", "status": "configured" },
{ "name": "runway_years", "value": 4, "unit": "years", "asOf": "2026-01-01T00:00:00Z", "status": "provisional" },
{ "name": "state_bytes_per_gas", "value": null, "unit": "bytes/gas", "asOf": null, "status": "pending" }
],
"reason": "live-state growth not measured",
"help": "Gas per second that keeps state within what one node can hold over the runway."
},
{
"area": "networking",
"value": null,
"unit": "Mgas/s",
"tag": "not-modeled",
"formula": "none yet",
"inputs": [],
"reason": "gossip and peer limits unknown",
"help": "Gas per second at which blocks still propagate within the slot."
}
],
"guardrails": [
{
"id": "da-utilization",
"label": "DA utilization",
"value": 42,
"unit": "%",
"threshold": 80,
"comparator": "<=",
"thresholdTag": "set",
"owner": null,
"asOf": "2026-01-02T00:00:00Z",
"status": "ok",
"help": "Share of blob capacity used at the current rate."
},
{
"id": "rpc-availability",
"label": "RPC availability",
"value": 99.5,
"unit": "%",
"threshold": 99.9,
"comparator": ">=",
"thresholdTag": "set",
"owner": null,
"asOf": "2026-01-02T00:00:00Z",
"status": "breached",
"help": "Successful RPC responses over the window."
},
{
"id": "validator-keep-up",
"label": "Validator keep-up",
"value": 3,
"unit": "blocks",
"threshold": 5,
"comparator": "<=",
"thresholdTag": "provisional",
"owner": "Synthetic owner",
"asOf": "2026-01-01T00:00:00Z",
"status": "ok",
"help": "p90 distance of validators behind the tip. Threshold is a placeholder until the pod sets one."
},
{
"id": "rpc-p99",
"label": "RPC p99 latency",
"value": 180,
"unit": "ms",
"threshold": null,
"comparator": "<=",
"thresholdTag": "unset",
"owner": null,
"asOf": "2026-01-02T00:00:00Z",
"status": "unknown",
"help": "Slowest 1% of RPC responses. No operational rule yet, so no status."
}
],
"translations": {
"gasPerPayment": {
"value": 52000,
"unit": "gas",
"derivation": "Median gas of a synthetic reference token transfer over the window.",
"window": "week"
},
"gasPerSwap": null
},
"sections": [
{
"id": "da",
"title": "Data availability",
"summary": "Synthetic DA observations.",
"metrics": [
{ "label": "Blob utilization", "status": "observed", "value": 42, "unit": "%", "window": "day", "note": "Invented.", "query": "synthetic.blob_utilization" },
{ "label": "Confirmed drain", "status": "not-measured", "value": null, "unit": "KB/s", "window": null, "note": "No query yet." }
],
"gaps": ["Confirmed drain"]
}
],
"work": [
{
"area": "execution",
"title": "Synthetic unified binary",
"status": "In progress",
"owner": "Synthetic owner",
"hypothesis": "Fewer process hops per block speed up block processing.",
"change": "Run the consensus and execution clients in one process.",
"expected": "about 20% faster block processing",
"realized": "18% faster on a synthetic before/after",
"evidence": { "label": "Synthetic run", "url": "https://example.com/synthetic/runs/1" },
"linear": {
"projectId": "synthetic-project",
"state": "started",
"progress": 0.4,
"scopeDone": 4,
"scopeTotal": 10,
"targetDate": "2026-03-01",
"updatedAt": "2026-01-01T12:00:00Z",
"url": "https://example.com/synthetic/linear/project"
},
"links": []
},
{
"area": "da",
"title": "Synthetic blob batching change",
"status": "Proposed",
"owner": null,
"hypothesis": "Denser batches post fewer bytes per gas.",
"change": "Not yet specified.",
"expected": null,
"realized": null,
"evidence": null,
"linear": null,
"links": [{ "label": "Synthetic doc", "url": "https://example.com/synthetic/doc" }]
}
]
}
49 changes: 35 additions & 14 deletions app/scaling/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,28 @@ import { Card } from '../components/ui/Card';
import { EmptyState } from '../components/ui/EmptyState';
import { Text } from '../components/ui/Text';

import { parseSnapshot, type Metric, type Snapshot, type WorkItem } from './snapshot.mjs';
import { isStale, parseSnapshot, type Ladder, type Metric, type Rung, type Snapshot, type WorkItem } from './snapshot.mjs';

// The snapshot is a runtime file, so render per request rather than at build.
export const dynamic = 'force-dynamic';

const STALE_AFTER_DAYS = 7;
const STALE_AFTER_DAYS = 10;
const DAY_MS = 86_400_000;

type Loaded =
| { kind: 'unconfigured' }
| { kind: 'invalid'; errors: string[] }
| { kind: 'ok'; snapshot: Snapshot; ageDays: number };
| { kind: 'ok'; snapshot: Snapshot; ageDays: number; stale: boolean };

async function loadSnapshot(): Promise<Loaded> {
const path = process.env.SCALING_SNAPSHOT_PATH;
if (!path) return { kind: 'unconfigured' };
try {
const result = parseSnapshot(JSON.parse(await readFile(path, 'utf8')));
if (!result.ok) return { kind: 'invalid', errors: result.errors };
const ageDays = Math.floor((Date.now() - Date.parse(result.snapshot.collectedAt)) / DAY_MS);
return { kind: 'ok', snapshot: result.snapshot, ageDays };
const { collectedAt } = result.snapshot;
const ageDays = Math.floor((Date.now() - Date.parse(collectedAt)) / DAY_MS);
return { kind: 'ok', snapshot: result.snapshot, ageDays, stale: isStale(collectedAt, new Date(), STALE_AFTER_DAYS) };
} catch (error) {
return { kind: 'invalid', errors: [error instanceof Error ? error.message : String(error)] };
}
Expand All @@ -51,7 +52,7 @@ export default async function ScalingPage() {
);
}

const { snapshot, ageDays } = loaded;
const { snapshot, ageDays, stale } = loaded;
return (
<div className="flex flex-col gap-10 pb-8">
<header className="flex flex-col gap-3">
Expand All @@ -60,13 +61,13 @@ export default async function ScalingPage() {
As of {formatTime(snapshot.collectedAt)} ({ageDays === 0 ? 'today' : `${ageDays}d old`}) · manually refreshed
snapshot, not live data. {snapshot.context}
</Text>
{ageDays > STALE_AFTER_DAYS ? (
{stale ? (
<Banner>Stale: this snapshot is older than {STALE_AFTER_DAYS} days. Refresh it before using these numbers.</Banner>
) : null}
</header>

<section className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
{snapshot.headline.map((m) => (
{headline(snapshot.ladder).map((m) => (
<Card key={m.label} className="flex flex-col gap-1 bg-background p-4 dark:bg-white/5">
<Text variant="label" tone="muted">{m.label}</Text>
<Value metric={m} large />
Expand Down Expand Up @@ -122,9 +123,26 @@ export default async function ScalingPage() {
);
}

const STATUS_LABEL = { observed: '', partial: 'Partial', unavailable: 'Unavailable', 'not-measured': 'Not measured' };
type Shown = Omit<Metric, 'status'> & { status: string };

function Value({ metric, large = false }: { metric: Metric; large?: boolean }) {
function headline(ladder: Ladder): Shown[] {
const rungs: [string, Rung][] = [
['Observed gas/s (p50)', ladder.observed.p50],
['Operating point', ladder.operatingPoint],
['Configured limit', ladder.configuredLimit],
['Qualified sustained', ladder.qualified],
];
return rungs.map(([label, r]) => ({
label, status: r.value === null ? r.tag : 'observed', value: r.value, unit: r.unit, window: r.window, note: r.help, source: r.source,
}));
}

const STATUS_LABEL: Record<string, string> = {
observed: '', partial: 'Partial', unavailable: 'Unavailable', 'not-measured': 'Not measured',
'not-modeled': 'Not modeled', 'not-established': 'Not established',
};

function Value({ metric, large = false }: { metric: Shown; large?: boolean }) {
if (metric.value === null) {
return (
<span className="w-fit rounded-md border border-dashed border-bds-gray-40 px-2 py-0.5 text-[13px] text-bds-gray-60">
Expand All @@ -143,11 +161,13 @@ function Value({ metric, large = false }: { metric: Metric; large?: boolean }) {
);
}

function MetricDetails({ metric, snapshot }: { metric: Metric; snapshot: Snapshot }) {
function MetricDetails({ metric, snapshot }: { metric: Shown; snapshot: Snapshot }) {
const window = metric.window ? snapshot.windows[metric.window] : null;
return (
<details className="text-[13px] text-bds-gray-60">
<summary className="cursor-pointer select-none">{window ? window.label : 'No measurement yet'} · details</summary>
<summary className="cursor-pointer select-none">
{window ? `${window.label} · details` : metric.value === null ? 'No measurement yet · details' : 'Details'}
</summary>
<div className="mt-1 flex flex-col gap-1">
{window ? <p>{formatTime(window.start)} → {formatTime(window.end)}</p> : null}
<p>{metric.note}</p>
Expand All @@ -162,8 +182,8 @@ function WorkCard({ item }: { item: WorkItem }) {
const rows = [
['Hypothesis', item.hypothesis],
['Change', item.change],
['Expected impact', item.impact],
['Evidence needed', item.evidence],
['Expected impact', item.expected ?? 'Not estimated'],
['Realized impact', item.realized ?? 'Not measured'],
];
return (
<Card className="flex flex-col gap-2 bg-background p-4 text-[13px] dark:bg-white/5">
Expand All @@ -173,6 +193,7 @@ function WorkCard({ item }: { item: WorkItem }) {
<p key={term}><span className="text-bds-gray-60">{term}:</span> {text}</p>
))}
<div className="flex flex-wrap gap-3">
{item.evidence ? <ExternalLink link={item.evidence} /> : null}
{item.links.map((l) => <ExternalLink key={l.url} link={l} />)}
</div>
</Card>
Expand Down
Loading
Loading