Skip to content

Deployment profiles and capacity

The platform’s default demo appliance is a compact single node. An optional six-node capacity profile uses the same Ansible roles, APIs, runtime model, and application deployment path when additional placement and compute headroom are useful.

Compact single-node profile

make up provisions every platform capability on single-01, a 4 vCPU / 16 GiB / 64 GiB Ubuntu VM. It includes four shared workerd members, two native Durable Object shards, all data services, ingress and control APIs, the product portals, the complete observability stack, and trusted local HTTPS for Worker ingress.

The single node is intended for evaluation, personal self-hosting, and small design-partner installations. It has no host fault isolation: losing the VM loses every service until that VM is recovered. Service memory values are ceilings rather than reservations; the compact inventory lowers the aggregate observability and high-volume service ceilings to keep the host recoverable.

Only one local profile can own ports 8080–8083 and 9090 at a time. Switch without deleting disks:

make down
make up

# Start the optional capacity profile later:
make multi-up

Run make capacity-check to create a temporary Standard-tier organization, deploy 32 distinct sum Workers, invoke each repeatedly through HAProxy, report guest memory/disk/load evidence, and delete the temporary organization and its Workers afterward.

The reference 4 vCPU / 16 GiB / 64 GiB profile has been exercised with the complete platform, all curated examples, 32 additional logical Workers, and 128 concurrent verification requests. That run completed without a failed service or request while using 3.01 GiB of memory, 6.9 GiB of root disk, and a 0.58 one-minute load average. These figures establish a practical low-traffic baseline, not a universal capacity promise: Worker code, object volume, queue backlogs, telemetry retention, and request concurrency determine the real ceiling. An 8 vCPU / 32 GiB host is a straightforward way to buy operating headroom without changing the topology.

Six-node capacity profile

Run make multi-up to create the six-node profile. Its additional nodes are capacity and placement targets, not HA replicas. No database, queue, object, or telemetry state is mirrored, and the profile makes no quorum or automatic state-failover claim.

Default placement

Node Capacity Disk Placed capabilities
control-01 4 vCPU / 6 GiB 32 GiB HAProxy, Data Plane API, control, identity, quotas, Access, tenant, admin, and status portals
compute-01 6 vCPU / 8 GiB 24 GiB Four shared workerd pool members
compute-02 6 vCPU / 8 GiB 24 GiB Four additional shared workerd pool members
data-01 4 vCPU / 8 GiB 96 GiB Object storage, static assets, and Images
data-02 4 vCPU / 12 GiB 64 GiB Queues, key-value, databases, vector search, and two native Durable Object shard members with Cron coordination
observe-01 4 vCPU / 10 GiB 64 GiB Prometheus, Loki, Tempo, and Grafana

Lima disks are sparse maximums rather than immediately allocated host usage. The multi-node profile requests 28 virtual CPUs and 52 GiB of memory, leaving room on the intended 40-core, 128 GiB development host for load generators and normal desktop work.

Compute scheduling

runtime_members in infra/ansible/inventory/group_vars/all.yml is the schedulable runtime set. HAProxy uses consistent hashing on the organization and Worker name for ordinary requests and health-checks every member. Both compute nodes can load any deployed immutable Worker version from the control plane, so adding compute-02 expands the same pool rather than creating a standby copy.

The control plane considers the runtime dependency ready when at least runtime_min_available members respond. That setting is a readiness floor, not a replication factor. HAProxy removes unhealthy members from request selection.

Deployments remain fleet-wide logical releases: Wrangler stores one immutable version and publishes one route. It does not select a host or create a per-Worker unit. A healthy runtime member loads the selected version on demand.

Data placement

Data capabilities are assigned by inventory groups (storage, assets, images, queues, key_value, and databases). The default inventory spreads those services over data-01 and data-02 to provide resource headroom and reduce contention. This is explicit placement, not data replication or transparent failover. Moving a stateful capability requires an intentional data migration; adding a host alone does not copy its state.

durable_runtime_members is the fixed native Durable Objects pool. Each stateful application is assigned one stable member and keeps that assignment as capacity is added. Members can be declared on both data nodes, but an application’s namespaces are not distributed or replicated between them. See Durable Objects for update and migration boundaries. Organization Cron coordinators use the same placement mechanism and native alarm storage; the control node does not poll a schedule table.

Private fleet network

Every node joins a full-mesh WireGuard network at 10.77.0.0/24. Keys are generated on the nodes during provisioning. Private service listeners bind to their WireGuard address, and UFW admits their ports only on wg0. Lima exposes the public and management endpoints from control-01 and the operator observability endpoints from observe-01, always onto host loopback.

The Lima user-v2 network is only the WireGuard underlay. Application services do not trust it directly.

Platform operations views

The administrator portal presents declared topology and live host pressure under Platform → Fleet. Selecting a host opens a focused detail view for its resource pressure and assigned service health; service placement is not repeated as a second fleet-wide inventory. These native views are backed by Prometheus data; Grafana remains an operator troubleshooting tool rather than the platform’s primary interface.

The unauthenticated status surface at http://status.ermahgerd.localhost:8083 uses the same platform-owned health and SLO signals. It intentionally excludes customer Worker response codes, so a faulty tenant deployment cannot report the platform itself as unhealthy.

Changing capacity

Resource envelopes live in infra/lima/single/*.yaml and infra/lima/fleet/*.yaml. Placement and private addresses live in infra/ansible/inventory/hosts*.yml and infra/ansible/inventory/host_vars/. Compute capacity additionally requires entries in runtime_members; each entry must have a unique name and endpoint. Run make infra-check after changing the topology, then recreate nodes whose Lima CPU, memory, or disk configuration changed and run make site or make multi-site for the matching profile.

tools/fleet.py intentionally manages one declared profile at a time. Ordinary lifecycle targets select single; multi-* targets select fleet. Capacity membership remains declarative and reviewable rather than being discovered from whatever Lima instances happen to exist.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close