Parallel Fetch, Raw Cache, and Run Logs
Reproducible pipelines beat live API roulette
Twenty-six minutes after the CLI refactor, a month-end report that took the better part of an hour still failed the only test that matters: can you re-run it and defend the number? On 2026-06-01 at 09:58, commit 336332d added parallel workers, a _raw.json cache, run logging, and individual production sheets - treating metrics like a small data pipeline, not a hero script.
Here's what this piece covers: why slow untrusted reruns kill staffing conversations, what 336332d shipped, how Phase 1 → Phase 2 → cache → run log fits together, the named pattern, and three lead habits.
Part of Field Notes: agentic delivery.
1. The leadership problem
Slow reports do not get run. Stale reports get argued about. When a VP asks why prs_merged moved week over week, "the API felt different" is not an answer - you need an audit trail.
Wrong: "We parallelized for speed."
Right: "336332d same day as the CLI refactor: parallel fetch, cached raw JSON, run log so we can diff two staff meetings."
The anti-pattern is the stateless hero run - re-fetch everything live, lose the trail, then blame GitHub when the spreadsheet disagrees with last Tuesday.
2. What the git history shows
| Time (EDT) | Commit | What landed |
|---|---|---|
| 09:32 | 9d47215 |
Modular CLI (analyze / export / run) |
| 09:58 | 336332d |
--workers, --pr-resource-workers, _raw.json, _run.log, person summary sheet |
Verified: 336332d message is Add parallel fetch, run logging, cache, and individual production metrics. Same morning as productization - operating concerns, not a later polish pass.
3. What I built
Phase 1 - GitHub search builds PR number catalogs (created, merged, activity, open-at-end candidates) in parallel where the queries allow.
Phase 2 - Per-PR detail fetch (~6 gh api calls each: metadata, commits, files, events, reviews, comments). ThreadPoolExecutor in pipeline/runner.py; defaults are --workers 4 and --pr-resource-workers 5. Serial baseline uses pr-resource-workers 1 when you need to prove rate-limit behavior.
Cache - _raw.json holds the raw payload so --from-cache rebuilds TSV/Excel without re-hitting the API. Filename convention: {repo}_{start}_to_{end}.*.
Run log - auth checks, progress, skips, errors. First file to open when a run fails mid-staff-prep.
Shape of the contract (manager-safe sketch):
# pipeline idea - fetch once, recompute many times
def run_month(repo: str, start: str, end: str, *, from_cache: bool) -> None:
log = RunLog(f"{repo}_{start}_to_{end}_run.log")
if from_cache:
payload = load_raw_cache(repo, start, end)
log.info("loaded _raw.json; skipping Phase 1/2")
else:
catalogs = discover_prs(repo, start, end) # Phase 1
rows = fetch_pr_details(catalogs, workers=4) # Phase 2
payload = save_raw_cache(repo, start, end, rows)
write_person_summary(payload) # rollups always recomputed on exportLater the same day, f19d1fc documented search date filters and API rate limits after large-repo runs hit limits - document the ceiling; do not silent-truncate. Cache stale summaries bit us when column schema moved (auditing agent analytics).
4. Named pattern: raw cache + run logs
Raw cache + run logs - parallel fetch for speed; cached raw JSON for reproducibility; a run log so two staff meetings can be diffed.
| Artifact | Role |
|---|---|
| Phase 1 catalogs | Scope of the window |
| Phase 2 detail rows | Expensive facts |
_raw.json |
Accelerant for rebuilds - not eternal truth |
_run.log |
Evidence when someone challenges the sheet |
What broke: treating cache as source of truth after schema change. Rollups must recompute on export; the raw payload is the durable layer.
5. What I'd do as a lead
- Require a
_run.logattachment when someone challenges a report. Memory is not an audit trail. - Treat cache as accelerant, not source of truth. Recompute rollups on export; re-fetch when the column contract changes.
- Cap parallel workers in CI; full parallelism for local month-end runs. Rate limits are an ops problem - tune them explicitly.
Further reading
- Your Slack script just shipped -
9d47215· CLI threshold - The afternoon we shipped three wrong metrics - same-day definition fixes
- Field notes: agentic delivery - series intro
- github-analysis: commit
336332d· 2026-06-01 ·docs/architecture.md