Repository navigation
perf(stack): start independent eager services concurrently - #6809
Conversation
There was a problem hiding this comment.
🤖 AI Review
All three reported findings are confirmed. The two orchestrator findings are minor polish issues; the defensive branch is unreachable in the current code. The test finding is a real timeout guard issue, although the integration suite has a 30-second outer timeout. I found no confirmed production behavior regression.
Findings
| Severity | Location | Category | Sources | Claim |
|---|---|---|---|---|
| 🟡 MINOR | packages/stack/src/Orchestrator.integration.test.ts:393 |
test-robustness |
codex | The lazy-service test can wait past its five-second observer timeout because it joins the observer again before checking the timeout result. The interruption test repeats the pattern. |
| ⚪ NIT | packages/stack/src/Orchestrator.ts:659 |
error-handling |
claude | The defensive missing-completion branch returns a bare failure, bypassing the per-instance outcome wrapper if it ever runs. |
| ⚪ NIT | packages/stack/src/Orchestrator.ts:708 |
maintainability |
claude | startComposition duplicates settle's failure aggregation and final observation logic, so changes to that result contract would require edits in both places. |
Stats
Claude findings: 2 · Codex findings: 1 · Confirmed: 3 · Refuted: 0 · Uncertain: 0
Models: claude-opus-5-5 + gpt-6-sol · Trigger: auto · Workflow run
This review runs once per PR. A maintainer can request another with a /ai-review comment.
kanadgupta
left a comment
There was a problem hiding this comment.
LGTM! non-blocking feedback below
One non-blocking suggestion inline about routing the new block through
settlewith aconcurrencyargument. It's a smaller version of the point the AI review raised on the now-resolved thread, and it also removes the only failure path that can bypass the per-instance outcomes wrapper.
Eager composition startup waits for each service to become healthy before starting the next, even when they are independent. Start independent branches concurrently and gate each dependent on readiness of its immediate prerequisites.
Preserve lazy route arming, lifecycle ownership and cancellation, ordered per-instance failure outcomes, and reverse-dependency shutdown. Report blocked dependents before preparing or launching them when a prerequisite fails.
Supabase service startup order
This is the actual dependency graph built by
makeSupabaseComposition, shown with all services selected and configured as eager. Public endpoints are bound first. Each arrow means the source must be healthy before the target starts; a target with multiple incoming arrows waits for all of them.flowchart LR subgraph roots["Start concurrently after endpoint binding"] db["PostgreSQL / database"] mail["Mail"] imgproxy["Imgproxy"] functions["Functions"] end db --> rest["REST / PostgREST"] db --> realtime["Realtime"] db --> pgmeta["pg-meta"] db --> analytics["Analytics"] db --> pooler["Pooler"] db --> auth["Auth"] mail --> auth db --> storage["Storage"] imgproxy --> storage pgmeta --> studio["Studio"] analytics --> studio functions --> studio analytics --> vector["Vector"]These are dependency constraints, not global startup phases: a ready branch advances immediately. Functions receives a database URL as configuration but has no database readiness dependency. Excluded services remove their corresponding managed edges.
With the default activation policy, PostgreSQL and services without public endpoints are eager; other services are lazy. Eager services pull in their prerequisites, while the remaining lazy services only arm their routes after their prerequisites settle and launch on demand. The diagram above shows the concurrency available when the complete graph is started eagerly.