VectorCI
An on-demand CI control plane that starts an isolated runner for a job, records the execution, and returns the infrastructure to zero capacity.
- 01Job queued
- 02Signed event
- 03Capability matched
- 04Runner starts
- 05Job executes
- 06Evidence recorded
- 07Runner stops
Why I built it
VectorCI began after I repeatedly exhausted the GitHub Actions minutes included with my account. I moved the workload to CircleCI, which worked well, but my bill settled into a $15 subscription plus two $15 credit refills in a typical month.
CircleCI was good, but the recurring cost was more than I wanted to pay. I decided to own the execution layer instead, making admission, scheduling, runner isolation, capability routing, teardown, and cost accounting systems I could design and operate directly.
The result is a control plane that starts repository-isolated capacity only when a signed job arrives, records what ran, and shuts the runner down when the job is complete.
The product problem
Self-hosting trades a predictable subscription for a harder operating problem. Different jobs may need macOS, Windows, CUDA, Houdini, a physical device, signing keys, or production access, and those environments should never be treated as interchangeable.
I wanted to keep the familiar GitHub workflow while moving runner selection, temporary capacity, execution records, and shutdown into a control plane I could understand and operate.
How I approached it
Each runner route describes one concrete environment and belongs to one repository. A job only starts when its full set of requirements matches.
The control plane verifies each incoming event, records the job, reserves a worker, and starts only the machine assigned to that repository.
When the job finishes, VectorCI records the execution and provider cost, unregisters the runner, and stops the service so idle compute does not linger.
How the product works
- 01
Receive
The control plane validates the GitHub App signature and persists the queued workflow-job delivery.
- 02
Match
Repository identity and the complete label set resolve to one exact capability pool. No cross-capability fallback is allowed.
- 03
Serialize
A durable pool slot admits a single job and restarts only the stopped, successful deployment bound to that repository.
- 04
Prove and teardown
Execution, cost, and runner identity are recorded before unregistration and service shutdown return the pool to zero capacity.
Decisions that make it different
Isolation is the default
Each worker belongs to one repository, so jobs never share a long-lived machine or cross project boundaries.
Capabilities stay explicit
A job asking for CUDA, signing, a device, or Houdini waits for the right environment instead of running somewhere merely similar.
Shutdown is part of success
A job is not complete until its execution record is stored, the runner is unregistered, and the temporary capacity is stopped.
What I built
- 616 completed jobs across 499.4 measured self-hosted minutes.
- $1.88 in measured Railway usage for the recorded workload, compared with my typical $45 CircleCI month.
- Signed job admission, repository-isolated runners, automatic activation, execution records, teardown, and unregistration.
- Defined runner profiles for Linux, Docker, Apple, Windows, Android, devices, signing, CUDA, Houdini, and deployment work.
How it fits the lab
VectorCI sits on the build and operations side of the lab. It gives me an observable, cost-aware execution layer for building and validating products.
The system applies the same product principles—clear state, bounded authority, evidence, and recovery—to the infrastructure behind the products.
Product and technical scope
I defined the product, designed the runner and trust model, built the control plane, integrated the infrastructure provider, and operated the system.