How It Works

We believe in transparent, understandable systems. This diagram shows the core data flow:


[ GitHub Repo ]

|

| (1) Polls for changes (git push, PR)

|

[ Polling Dispatcher ]

|

| (2) Enqueues job

|

[ SQLite Job Queue ]

|

| (3) Dequeues job

|

[ HorseCI Runner ] --- (git worktree) ---> [ Local Cache ]

|

| (4) Reports status/logs

|

[ GitHub Checks API ]

HorseCI's architecture prioritizes simplicity and robustness through deliberate technical trade-offs. Our goal is a system that is both fast and easy to reason about.

* Polling Dispatcher: For our initial implementation, we chose polling over webhooks for its implementation simplicity and reliability guarantees. While this introduces some latency (typically 10-30 seconds), it ensures no events are missed without the complexity of managing a webhook consumer service with retries and dead-letter queues. For side projects and small teams, this trade-off favors simplicity over sub-second trigger latency.

* SQLite Job Queue: A simple, robust, embedded database manages the job queue on each host. This avoids the operational complexity and network latency of a separate database server or message broker for this core task. We acknowledge this creates a single point of failure for the dispatcher—if the host fails, queued jobs are lost. Runners already executing jobs will complete normally. For our current scale and target use case (side projects, small teams), this is an acceptable trade-off. We plan to add replication for higher availability as we grow.

* Isolated git worktree Checkouts: Instead of fresh clones, we use git worktree to create pristine, isolated filesystem environments for each job. This is significantly faster and more efficient for repositories of all sizes.

Limitations & Future Work

We are upfront about our current limitations:

Single Point of Failure: The polling dispatcher currently runs on a single host. If it fails, new jobs will not be scheduled until it recovers. Runners already executing jobs will complete normally. This is acceptable for side projects but not for mission-critical enterprise CI. We are working on a replicated dispatcher design.

Polling Latency: Jobs start 10-30 seconds after the triggering event. This is fine for most development workflows but not suitable for urgent production hotfixes requiring immediate CI feedback.

No Horizontal Scaling (Yet): The current architecture is designed for single-tenant, small-to-medium scale. We will add horizontal scaling as we approach capacity limits.

Runner Performance

Our runners are designed for maximum speed and efficiency.