Skip to content

perf(host-cloudflare): reconcile internal integrations on a cron instead of at isolate boot - #24

Merged
fforres merged 2 commits into
skywardfrom
perf/reconcile-cron
Oct 18, 2026
Merged

fforres merged 2 commits into
skywardfrom
perf/reconcile-cron

Conversation

@fforres

@fforres fforres commented Oct 18, 2026

Copy link
Copy Markdown

Why

Every new isolate awaited a sequential reconcile of all internal integrations before it served its first request. Production traces showed about 4 s of wall time per cold isolate, and every request that landed on one waited for it: /api/*, /mcp, and the internal service-binding door.

What changes

  • Reconcile runs every minute from a cron trigger (scheduled handler with ctx.waitUntil). The fetch path no longer runs it.
  • Entries run concurrently (concurrency: "unbounded"). Each entry already catches its own failure.
  • wrangler.jsonc declares "triggers": { "crons": ["* * * * *"] }.

Trade-off

A new internal integration, or a changed tool list, appears within about a minute instead of at isolate boot. With wrangler dev, reconcile now runs only when scheduled is triggered by hand.

Tests

  • reconcile.test.ts: all entries start before any of them is released.
  • worker.test.ts: fetch never calls reconcile, and scheduled runs one pass inside waitUntil.
  • host-cloudflare typecheck and oxlint pass.

https://claude.ai/code/session_019ZE3j9YzRKxT4LaiDCBv6S

…ead of at isolate boot

Cold isolates waited about 4 s on a sequential reconcile of every internal
integration before serving any request (API, MCP, internal door). Reconcile
now runs every minute from a cron trigger via a scheduled handler, all
entries concurrently, and the fetch path no longer touches it.

A new internal integration or a changed tool list now appears within about
a minute instead of at isolate boot.

Claude-Session: https://claude.ai/code/session_019ZE3j9YzRKxT4LaiDCBv6S
…th the reconcile cron

The cron reuses the per-isolate D1 handle instead of reopening D1 every
minute (a failed open is retried), builds its executor on
makeCloudflareExecutionStackLayer, and loads config inside a single
Effect.gen so a throw still ends in the "never throws" warning.

Claude-Session: https://claude.ai/code/session_019ZE3j9YzRKxT4LaiDCBv6S
@fforres
fforres merged commit 1aa402d into skyward Oct 18, 2026
4 of 40 checks passed
@fforres
fforres deleted the perf/reconcile-cron branch October 18, 2026 01:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant