Public: anyone can read this; the crew can change it.

Placement policy: owned capacity first, burst spills to cloud above the slider's threshold #509

shipped production is serving it opened this has it
opened this

The owner's intent: run owned metal at full capacity and spill only bursts to cloud. Today every app runs in this process and the spawn seam (src/spawn/placement.ts) only knows hosted. This run is the decision, not a new body.

Acceptance:

  • [x] src/core/placement_policy.ts: pure placeFor({ ownedUsed, ownedCapacity, spillAtOwnedUse, alwaysOn, preference }) → owned | cloud with a one-sentence reason; production prefers owned; a preview spills first; an app's placement: metal|cloud in app.yaml is a preference the policy honours unless owned is full
  • [x] the decision is written to the decision ledger (core/decisions.ts) and onto the meter interval, so cost knows which price applies
  • [x] with no cloud body configured every decision is owned and the board says "no cloud body: bursts queue" — never silently
  • [x] the platform label for owned nodes (plat.sh/site=vxrail) is a setting, not a constant, passed through to whatever body implements it
  • [x] tests: below threshold → owned; above → cloud for previews first; full owned + no cloud → owned with the queue reason

Files: new src/core/placement_policy.ts, src/spawn/placement.ts, src/core/decisions.ts. Holds up #391 (services need a placement lever).

Part of the profit slider (#392); the shape is docs/PROFIT.md.

commented

Released from Later to use the week's subscription: Behind pace: 75% of the week left with 21% of its time gone, reset 2026-11-15 02:00 UTC, burning 0% an hour against 0.5% allowed; speeding up to 5 of 5 slots and releasing the next issue.

commented

Reviewed pull #10193 at its head: ticked src/core/placement_policy.ts: pure placeFor({ ownedUsed, ownedCapacity, spillAtOwnedUse, alwaysOn, preference }) → owned | cloud with a one-sentence reason; production prefers owned; a preview spills first; an app's placement: metal|cloud in app.yaml is a preference the policy honours unless owned is full; the decision is written to the decision ledger (core/decisions.ts) and onto the meter interval, so cost knows which price applies; with no cloud body configured every decision is owned and the board says "no cloud body: bursts queue" — never silently; the platform label for owned nodes (plat.sh/site=vxrail) is a setting, not a constant, passed through to whatever body implements it; tests: below threshold → owned; above → cloud for previews first; full owned + no cloud → owned with the queue reason.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs