Skip to content

Starforge — Overview & Build Flow

Starforge is a BuildService port inside Starbase Worker, not a separate binary. It abstracts build execution so the build backend can be swapped without changing core logic.

§16.1 Decision Rationale

Starform does not run its own build infrastructure at launch. Running a multi-tenant BuildKit fleet with rootless isolation, cache tuning, and incident response is 3–4 months of upfront engineering plus ~10–20% of one engineer's ongoing time — a cost that pre-seed capital is better deployed elsewhere (egress differentiation, Layers, observability, billing). Builds are also the most visible reliability surface of a PaaS: every customer sees every build, and early rough edges damage trust disproportionately.

Starforge's MVP adapter uses Depot SaaS — a remote BuildKit service with a programmatic API designed for "build on behalf of customers" use cases. Fly.io, Hathora, and other platforms run on this pattern. Depot handles the compute, cache, and infrastructure; Starform handles the integration and the customer experience layered on top.

The BuildService port abstraction keeps this swappable. When Depot spend exceeds ~$3–5k/month, or when a specific unmet requirement emerges (non-US data residency, custom frontends, GPU builds), a second adapter (adapter/buildkit/) can be added without touching core logic.

§16.2 MVP Flow

flowchart TB
  classDef built fill:#3434DC22,stroke:#3434DC,color:#5B5EE8;
  classDef third fill:transparent,stroke:#808080,color:#808080;
  classDef store stroke-dasharray:4 3,stroke:#808080;

  PUSH["Git push<br/>GitHub webhook"]:::third
  API["Starbase API<br/>enqueue build job"]:::built
  PICK["Starbase Worker<br/>picks up job · clones source · inspects repo"]:::built

  DECIDE{"Dockerfile at<br/>repo root?"}
  RAILPACK["Railpack library<br/>detects framework · generates LLB"]:::built

  SUBMIT["Starforge adapter → Depot API<br/>per-workspace project"]:::built
  DPATH["Dockerfile path<br/>BuildService.CreateBuild · Dockerfile frontend"]:::built
  RPATH["Railpack path<br/>BuildKitService · raw LLB submission"]:::built

  DEPOT["Depot<br/>ephemeral BuildKit · workspace-scoped cache"]:::third
  REG[("DO Container Registry")]:::store

  LOGS["Worker streams build logs<br/>Depot → ClickHouse"]:::built
  POLL["Worker polls build status → Postgres<br/>on success: update desired state w/ new image SHA"]:::built
  TICK["Next Shuttle tick<br/>picks up new image · deploys"]:::third

  PUSH --> API --> PICK --> DECIDE
  DECIDE -- "yes" --> SUBMIT
  DECIDE -- "no" --> RAILPACK --> SUBMIT
  SUBMIT --> DPATH
  SUBMIT --> RPATH
  DPATH --> DEPOT
  RPATH --> DEPOT
  DEPOT --> REG
  DEPOT --> LOGS --> POLL --> TICK
Diagram — MVP build flow (§16.2). A push fans into one of two Depot paths: a root Dockerfile goes straight to BuildService.CreateBuild; otherwise Railpack detects the framework and emits LLB submitted via BuildKitService. Both share one per-workspace Depot project, push to the registry, stream logs to ClickHouse, and end at a Shuttle tick. Brand-blue boxes are Starform-built; gray are third-party; dashed is a data store.

Cross-references

The BuildService port contract → §16.3 · the Dockerfile-vs-Railpack frontend strategy → §16.5 · log streaming to ClickHouse → §16.6 · the Git push + webhook entry point → §16.11 · the build state machine → §16.12 · the Worker binary that runs this → Starbase §14 · the desired state a finished build updates → Foundations §32.