Skip to content

Hardware sizing: a wider instance catalog, custom machines, and specs the engine acts on #29

Description

@snowfluke

What is missing

Three related gaps around hardware. A reader cannot pick most machines, cannot describe a machine
that is not on the menu, and cannot make any hardware spec change a result.

1. The catalog covers three component kinds. isSizedKind names eleven kinds, but only
service, db and cache carry a sizes array at any vendor. AWS ships 15 sizes, GCP 13, Azure
15. A worker, a replica set, a shard, a search index, a time series store, a graph store, a vector
store and a transcoder all get a product name and no picker, because VendorPanel renders the
picker only when mapping.sizes is non-empty.

That is not only a missing dropdown. costDesign pushes any mapped kind with no priced size onto
unpriced, so every design containing a worker reports a monthly total that silently excludes the
workers. Async worker topologies are a large share of the bundled examples.

The families on offer are also narrow. service gets general purpose only (t3, m6i, n2, e2,
D_v5). There is no compute optimised or memory optimised shape, which is the first thing anyone
sizing a real service compares.

2. There is no custom machine. An infra team runs shapes a catalog will never hold: a reserved
instance, a bare metal box, an on-prem server, a Kubernetes pod request and limit. Today those
cannot be expressed, so the tool can only price what the vendor files happen to contain. GCP
already uses custom machine types in this repo (db-custom-4-16384), so the vocabulary exists.

3. Specs that are collected but never used. VendorSize carries memory, network and
maxIops, each cited. Only vcpu does anything: derive.ts turns it into capacity. memory
prints as text in VendorPanel.tsx:79. network and maxIops are read nowhere in src/. So a
reader picks db.r6g.large, sees 16 GiB and "Up to 10 Gigabit", and neither number can ever
change a result.

Smaller, in the same area: chosen sizes live in localStorage keyed vendor:nodeId (sizing.ts),
so share links and exported .breakscale files arrive unsized and unpriced.

What would it teach

That CPU is rarely what breaks first. A student sizes a service for throughput, watches the queue
stay short, and still sees it die because each in-flight request holds 40 MB and the box has 16
GiB. Or the queue is healthy and the NIC is full at 1.2 Gbps. Right now the only way to fail in
Breakscale is to run out of slots or time, and that is the least common outage in practice.

A custom machine adds the sizing exercise itself: put the box you already own next to the box on
the menu and see which one survives the load.

The byproduct is that an infra or devops reader can take a design to provisioning: this is the
fleet, this is the shape, and this is the resource that binds first.

Rough shape

  1. Sizing becomes part of the design. Move the chosen size out of localStorage and into the
    topology, so export, import and share links carry it. This is a prerequisite for anything
    custom, since a machine the reader defined is worthless if it does not travel with the design.
  2. Widen the catalog. Sizes for the eight sized kinds that have none, and compute optimised
    and memory optimised families for service. Same rule as today: published spec, source URL,
    date read. This closes the hole in the cost total on its own.
  3. A custom machine. Name, vCPU, memory, network, IOPS, price per hour, entered by the reader.
    It runs through the same deriveFromSize and the same cost arithmetic as a catalog size.
  4. Resources become simulation dimensions. Per-request demand and per-node limit for memory,
    IOPS and bandwidth. Memory exhaustion sheds; IOPS and bandwidth saturation adds delay rather
    than failing outright. Mechanics are yours to decide; that is one plausible split.
  5. A provisioning readout. Per component: kind, shape, fleet, and the resource with the least
    headroom.

Keeping it honest

A custom machine is labelled user defined everywhere it appears. It never carries a source URL and
is never mixed into anything that claims to be published spec. Where a total is priced from a
reader's own figure rather than a published rate, the readout should say so.

Per-request demand would be user set, defaulting to unset. Unset shows nothing rather than a
guessed number, the way derive.ts returns null where there is nothing honest to say. No resource
figure would be derived from an instance size, and the derivation stays in one file.

This is the argument cost.ts already makes for money: a design trade-off the simulator cannot
currently show. And derive.ts already tells readers who want real behaviour to set the knobs
themselves. This is more knobs to set.

Anything you already tried

Checked against what is planned. TODO lists a networking layer (bandwidth and loss), which step 4
should fold into rather than duplicate. Issue #13 covers documenting how vendor sizes become
simulator numbers, which is adjacent: that explains the current derivation, this widens what a
size can affect.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:simSimulation engine (src/sim)discussionApproach not settled; open for discussionenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions