better/compute
Concepts

Domain model

Every entity Better Compute tracks, from regions and pools to atoms, bookings and commands, how they relate, and how each maps to a Better IAM resource type.

Every entity below is a TypeScript type in @better-compute/core and a table (or a column) in PostgreSQL. Records carry epoch-millisecond timestamps, and every tenant-scoped record carries its tenantId or ownerTenantId: no repository function reads an ambient tenant.

How the entities relate

Ids read <prefix>_<body>, where a generated body is a 26-character ULID in lower-case Crockford base32, so ids of one kind sort by creation time: site_, pool_, node_, prj_, rsv_, alloc_, inst_, cmd_, wf_, img_, prof_, jt_, pacct_, flv_, whk_, evt_ and others. Reservation and instance ids are derived from the request instead of generated, as the section on reservations below explains.

Regions, sites, pools and offerings

A is a geographic label in Better IAM's region-name grammar, stored on a site as iamRegion.

A is a boot and failure domain served by at least one bcd site agent. Its kind is shared or dedicated (the platform's hardware) or custom (a tenant's own hardware). A site agent is itself a nodes row with role: 'site'.

A is a scheduling and policy domain in one site, owned by one tenant:

FieldValues
classmetal-host, metal-dedicated, vps-host, provider
gpuModelExactly one GPU model family per pool, for example H100
sharingexclusive (default), mig, timeslice, mps
agentbcd (machines run the daemon) or none (reached only through a provider's API)
policyacceptance checks, overcommit ratios for scalars, lostAfter, disruptionBudget (default 0.05), admission.budgetCheck, maxPending, hardwareProfile, sharing.replicas, migLayout, tenantRoot
providerAccountIdFor provider pools, the account that backs them

An is a pool_offers row that makes a pool exist in another tenant's view, with a quota per resource (gpu, vcpu, …), an optional priority and includeDescendants. A resource missing from the quota grants zero. See pools.

Nodes

A is a server running bcd, or a provider machine that runs it. Its state is not one field but several independent axes, so each question has one answer:

AxisValuesChanged by
provisionStateadopting, adopted, enrolling, inspecting, commissioning, ready, deploying, deployed, releasing, rescue, failed, retiring, retiredWorkflows and the lifecycle controller
maintenancetrue or falseFailures, remediation, operators
cordonedtrue or falsenodes.cordon, nodes.uncordon, drains
poweron, off, unknownBMC drivers
connectivityconnected, disconnected, unreachable, lostSessions and the liveness controller
conditionsTyped conditions such as GpuCountMismatch, NodeUnreachable, ClockSkewHealth, inventory, liveness

Beside the axes a node has a role (unassigned, host, dedicated, site), a trust (platform, tenant-owned, tenant-controlled), an adapter naming how the control plane reaches it (bcd/v1, provider-api/v1), per-concern driver bindings, a and observedGeneration, and a : the SHA-256 of its normalized product UUID, serial number, permanent MACs and GPU UUIDs, trusted only when at least two independent identifiers survive the placeholder blocklist.

A node is schedulable only when all of these hold: provisionState is adopted or deployed, role is host, it is neither in maintenance nor cordoned, connectivity is connected, its noScheduleReasons list is empty, observedGeneration is at least 1, and its trust is platform (or tenant-owned in a pool its owner owns). See operating nodes.

Devices and atoms

A is a unit with typed attributes, in the style of Kubernetes dynamic resource allocation. Its class is gpu, gpu.mig (ids <gpuUuid>/gi<g>/ci<c>), gpu.slot (time-slice or MPS slots, <gpuUuid>/s<k>), nic.vf, disk or node. Only , devices with bookable: true, are ever booked; a partitioned GPU's parent is not bookable. Device ids are stable: GPU UUID, disk WWN, MAC.

GPUs carry two names. gpuProduct is the normalized NVML name (NVIDIA H100 80GB HBM3 becomes H100-SXM5-80GB); gpuModel is the family (H100), mapped through a versioned gpu-models.json. An unknown name maps to other and raises GpuModelUnknown. Pools, policies and meters use gpuModel; selectors may use either.

is the node's NodeInventory v1 document, sectioned and hashed, with append-only snapshots. is what the inventory makes bookable: allocatable, allocated, reserved and available, per pool and resource. See inventory and health.

Requests, reservations and bookings

A is a tenant's claim on a pool: devices (class, count, selector, topology), an optional start, a duration, and a binding:

  • hold (the default): CDI devices on the node, consumed by a workload manager there.
  • instance: a VPS instance's allocation.
  • node: a whole node deployed with the tenant's profile, in tenantRoot pools (v0.5).

A reservation starts as a whose id derives from the tenant, the caller's identity and the idempotency key (rsv_ plus the base32 SHA-256 of the three), so a retry finds the same row and Better IAM can decide on the exact request before it exists. Its states are draft, denied, awaiting-confirmation, pending, placed, binding, active, releasing, released, failed, cancelled and expired.

An is a placement on one node (a gang has one per node), owned by a reservation or an instance, listing its atoms and scalar amounts. A is one row (device_id, allocation_id, during) in device_bookings, where EXCLUDE USING gist (device_id WITH =, during WITH &&) allows one live booking per atom per instant. See reservations.

Leases

"Lease" is always qualified:

  • An is a renewable hold: a reservation made with leaseSeconds is released unless reservations.renew is called within every period.
  • A is a session's 40-second time to live.
  • A gives one worker or agent ownership with a fencing epoch: shard:<n>, pool:<id>, site:<id>:boot, singleton:<job>, gateway:<id>.

Instances, images and profiles

An is a VM, microVM or single-tenant container on an allocation, with a desiredState (running, stopped, deleted) and an observed state. An is a signed, content-addressed artifact (name@version, raw, qcow2 or iso, with a SHA-256), private or public, and verified once its signature checks out against a signer allowlist. A is a versioned provisioning template for metal or vps targets, with driver bindings, an image, user data, steps, host configuration and acceptance; it is immutable once a workflow used it.

Workflows, drivers and providers

A is a profile expanded for one target into persisted . Each step runs on control-plane, site, node or ramdisk, and may await: 'rejoin' for steps that end the agent's boot. A implements one or more concerns (power, management, boot, deploy, inspect, console, virtual-media, bios, raid, firmware, config, runtime). A is an external capacity API, configured as . See workflows and drivers.

Commands and desired state

A is a durable, idempotent one-shot message to one node, with a per-node seq, not_before, not_after, an optional min_generation, and the flags of its . A is the node's generation-numbered desired state. The difference between the two is the subject of desired state and commands.

Tenants, projects and admission

A is a Better IAM tenantId: the root tenant is the platform, organizations are customers. A is an application-owned grouping inside a tenant (the projects table). The is the IAM decision context recorded with each allowed mutation (identity, session kind, agent, delegation, request id) in audit_events, because Better IAM does not audit allows. Asynchronous work acts on that record, never on a stored token.

IAM resource types

Better Compute contributes these types to Better IAM's catalog, with the configurable prefix compute-. All of them are application-owned: Better Compute resolves them from its own projection and never registers them in Better IAM.

TypeWhat it isParentRelationsAttributes policies can read
compute-fleetThe platform fleetnonenonenone
compute-tenantA tenant's compute scopenonenonenone
compute-projectA projectnonemember, adminnone
compute-siteA sitenonenoneregion, iamRegion, kind
compute-poolA poolnoneviewer, user, operator, adminregion, class, gpuModel, gpuMemoryGb, sharing
compute-nodeA machinecompute-pooloperatorregion, gpuModel, gpuCount, lifecycle, trust, dedicatedTo
compute-reservationA GPU reservation, decided as a draftcompute-poolnoneregion, gpuModel, gpuCount, durationHours, binding, projectId, spot
compute-instanceA VPS instancecompute-poolnonevcpu, memoryGiB, gpus, imageId, imageVerified, projectId
compute-imageAn OS or ramdisk imagenonenonevisibility, verified
compute-profileA provisioning profilenonenonenone
compute-provider-accountAn account with a capacity providernonenonenone

The first three are scope types. compute-fleet has the single id global and resolves only in the root tenant; compute-tenant/{t} resolves only in tenant t; compute-project/{id} resolves in its owner tenant. Methods that act on a whole scope, such as pools.list or quotas.set, are decided on one of them.

Because reservations and instances have compute-pool as their parent, a policy can combine pool access and request limits in one decision: "users of this pool may reserve up to 8 H100s for at most 72 hours." See actions and resources for every action.

Was this page helpful?

Better Compute is created by Sean Filimon

Last updated

On this page