Where the time actually goes in an AI coding-agent job
I run an agent-orchestration platform: it takes a ticket, spins up a git worktree, lets a Claude Code agent build the feature, and runs a deterministic verify gate before merging. A typical job takes 20-30 minutes. I used to blame slow model responses for the runtime, but stage-by-stage measurements proved that assumption wrong: infrastructure overhead costs 5-8 minutes of every job before the agent even finishes. Here is where the time actually goes and how to optimize it.
The Baseline Overhead
On a standard dev machine (Windows 11, Bun, Next.js), a single job pays a heavy infrastructure tax:
| Stage | Measured Cost | Impact / Notes |
|---|---|---|
git worktree add |
Seconds | Negligible overhead. |
bun install |
~91s (median) | Cold worktree setup, even with a warm cache. |
| Lint & Typecheck | ~1-2 minutes | eslint + 2Γ tsc across the full repo with no shared cache. |
next build |
Minutes | The longest gate leg due to a cold .next directory every run. |
| Vitest | ~26 seconds | Fast and acceptable. |
| Model Time | ~15-22 minutes | Planning, execution, and review calls. |
Fixed infrastructure costs account for 20% to 30% of total runtime. Eliminating this overhead reduces small job times from ~30 minutes to ~20 minutes, leaving the remaining time strictly bounded by model inference.
Ranked Infrastructure Optimizations
1. A Pre-Warmed Executor Slot Pool (The Highest-Value Win)
Instead of creating a fresh worktree and running bun install from scratch for every job, maintain a small pool of pre-warmed directories containing:
- A long-lived Git worktree (re-pointed per job).
- A pre-installed
node_modulesdirectory (invalidated only when the lockfile hash changes). - Persistent build caches (
.next,tsconfig.tsbuildinfo,.eslintcache).
When a job starts, it claims a slot, checks out the target branch, and immediately executes. After completion, git clean resets the worktree while leaving cache directories intact. This eliminates the ~91-second install step on almost every job.
2. Persistent Next.js Build Caching
Next.js supports persistent filesystem build caching. Combining this with a warm slot pool carries the .next cache between jobs, turning the longest gate step from minutes into tens of seconds for standard diffs.
3. Incremental Linting and Typechecking
Adding --incremental to tsc and --cache to eslint within the persistent slot directory saves roughly 1 minute per job without changing verification outcomes.
4. Windows Filesystem Optimizations
Real-time Defender scanning severely throttles small-file I/O operations (like node_modules and .next writes). Adding directory exclusions or moving worktrees to a ReFS Dev Drive improves install and build I/O speeds by 2Γ to 5Γ with zero code changes.
5. Isolated Linkers (Proceed with Caution)
Switching to bun install --linker isolated provides pnpm-style symlinked stores, yielding faster warm installs. However, caution is required: symlinks spanning worktrees can cause catastrophic unintended deletions if cleanup commands traverse outside the worktree root.
Implementation Strategy
- Environment Tweaks: Exclude worktrees from real-time antivirus scanning (immediate win).
- Slot Pool Architecture: Build the persistent executor slot pool to retain installed dependencies and cache directories.
- Incremental Caching: Enable
tsc --incrementalandeslint --cache. - Framework Upgrades: Enable persistent build caching in Next.js once the slot pool is stable.
By optimizing the infrastructure pipeline, fixed job overhead drops from 5-8 minutes to under 60 seconds. The remaining runtime represents actual model reasoning-the exact phase worth waiting for.
I'm AndrΓ©as - full-stack dev, CTO at a B2B SaaS, building my own agent tooling. Portfolio: https://andreas-bodin.vercel.app
Comments
No comments yet. Start the discussion.