Why builds take so long and the fix
Answer me with artifact · 2026-10-25 22:27

New version 0.5.7

You have 0.5.5. Found when this page was made.

What's new:

Run in a terminal:

npx skills update answer-me-with-html -y

Or tell your agent:

Update answer-me-with-html
See what's new

Why builds take so long and the fix

A

How much faster

measured = from runs today; the rest are estimates until step 0 measures them
Build Today After steps 1–4 After the crate split
API deploy to Contabo (CI) 66–107 min, measured (one-job first run: 86 min) 15–25 min on our own builder with a warm build folder 5–10 min
Desktop build, no Rust change 60–120 min, measured tonight (machine overloaded) 8–12 min (UI + packaging; binaries reused) same
Desktop build with an API change 90+ min 20–30 min 10 min
CI tests ~50 min, measured 15–20 min (fast test profile) 5–10 min
  • 10 minutes is reachable for UI and Desktop builds with steps 1–4. API changes reach 10 minutes only after the crate split. With one 363,000-line crate, the compiler cannot go faster than one core on that crate.
  • Step 0 measures before we commit. One cargo build --timings of the API with today's settings and with a fast profile, on the builder. Then the estimates in this table become real numbers.
B

How sessions know a build already has their change

queue one buildSession merges commitMbuild-queue needdesktop --contains MDone build has M?return "already inb6331"Running build has M?wait for it, start nothingBuild queued? wait; itbuilds newest main, soit has MNone of these
  • Every build records the main commit it built. "Has my change" means git merge-base --is-ancestor M <built commit>. Git answers this exactly.
  • A queued build reads main when it starts, not when it was queued. Everything merged while it waited goes in. Ten sessions waiting means one build, not ten.
  • No polling. A session that must see its change live runs one wait that returns once, when a build with its commit is done. A session that does not need to see it live just merges and finishes.
  • Tests stay with the session, before merge (fast profile, only the crates it touched). Only release builds go through the queue.
C

Splitting the API into crates

It is the norm. Large Rust codebases are many crates in one workspace. The Rust compiler is about 70 rustc_* crates, Zed's editor has over 100 crates and Bevy has about 50. Google and Meta go further, with Bazel and Buck targets per small library.

What it does to the platform: nothing a user sees. It is still one allternit-api binary, the same routes, the same database and the same deploy. The shipped binary keeps LTO, so it runs as fast as it does now.

Debt and cost we take on:

Cost Why How we keep it small
One shared core crate 331 of the files use AppState, the one object that holds the database, auth and config Move AppState, db, auth and errors into api-core first; every area crate depends on it
Cutting cycles Route modules call into each other; separate crates cannot depend on each other in a circle Shared code moves to core; a few links become traits
Open branches conflict Moving files breaks every open PR that edits them One area per PR, announced, merged in a quiet window; pure moves, so git follows the renames
Wider visibility pub(crate) items become pub between crates Keep each crate's public surface small
More Cargo.toml files One per crate Versions stay in the workspace file, as now

Where to cut first: llm_gateway (25,000 lines) and agency_api (23,000 lines) depend only on db, auth and media. They come out first, after core.

D

Order of work

Step Work Gain Size
0 Measure: cargo build --timings, today's profile against a fast profile Real numbers in place of estimates 1 hour
1 Build queue with "contains my commit" No overlapping builds; one build per batch Small
2 Release train rule in AGENTS.md Sessions merge, the queue ships Small
3 Desktop reuses binaries whose source did not change Desktop build in ~10 min Small
4 Fast test profile, sccache in CI, Linux builds on our builder with a warm build folder CI 66–107 → 15–25 min Medium
5 api-core, then llm_gateway and agency_api crates, then the rest one area per PR API builds in ~10 min Large, in steps