Skip to content

Commit abb9ac9

Browse files
mpstatonclaude
andcommitted
issue(architecture): Refactoring for API Speed — single-user app boots in 60s+, should be ms
Diagnoses the boot-latency: a distributed mesh (7+ Railway services, per-remote WebSockets, NATS request/reply, remote SurrealDB Cloud, separate id.didi.sh auth) serving ONE user, where coordination cost dwarfs the work. Prime suspect is retry-as-readiness (the ~60s workspace.active retry + App.svelte's 8x loadWorkspaces backoff) masking a boot race. Lays out the measure-first design space, ordered by leverage. Refactor backlog, not fixed here. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018UYTYu4MAFZ7iyr2VTo2kq
1 parent 9843c23 commit abb9ac9

1 file changed

Lines changed: 118 additions & 0 deletions

File tree

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
title: "Refactoring for API Speed — a single-user app should boot in milliseconds, not a minute"
3+
lede: "Refreshing the page takes 60s+ for the logged-in workspaces to appear, and every microfrontend/microservice hop adds latency waiting for the others to respond or 'acknowledge' each other. There is ONE user. The distributed mesh — 7+ Railway services, per-remote WebSockets, NATS request/reply, a remote cloud DB, a separate auth service — imposes coordination cost that dwarfs the actual work. This is the diagnosis and the refactor design space, measure-first."
4+
date_created: 2026-08-02
5+
date_modified: 2026-08-02
6+
authors:
7+
- Michael Staton
8+
augmented_with:
9+
- Claude Code on Claude Opus 4.8
10+
semantic_version: 0.0.0.1
11+
tags:
12+
- Issue
13+
- Augment-It
14+
- Performance
15+
- Architecture
16+
- Refactor
17+
- Boot-Latency
18+
status: Open · Diagnosed · Refactor Backlog
19+
---
20+
21+
# Refactoring for API Speed
22+
23+
## Why Care?
24+
25+
On refresh, the workspaces the operator is logged into take **60s+** to appear.
26+
Interactions wait on microfrontends and microservices responding to — and
27+
"acknowledging" — each other. There is exactly **one user**. This should be
28+
milliseconds. The cost is not the work; it's the **coordination** between too
29+
many independently-deployed parts.
30+
31+
## The topology being paid for (with one user)
32+
33+
- **7+ separate Railway services**: `shell` (augment.didi.sh), `strategy-curator`,
34+
`chat` (+ other federation remotes: org-workbench, search-and-add,
35+
search-results…), `workspace-service` (WS gateway), `record-surrealdb-resolver`,
36+
`content-ingest`, `prompt-runner`.
37+
- **`id.didi.sh`** — a separate identity service (different repo/runtime) for
38+
JWKS verification + `/api/me` memberships.
39+
- **SurrealDB Cloud, aws-use1** (`wss://…surreal.cloud`) — every query is a
40+
network round-trip to AWS us-east.
41+
- Each **microfrontend opens its OWN WebSocket** to workspace-service and does
42+
its **own** auth handshake (shell App.svelte notes "each federation remote
43+
also connects, those instances are separate").
44+
- Services talk **service→service over NATS request/reply**.
45+
46+
Every one of those boundaries adds fixed latency: TLS, cold start, DB round
47+
trip, NATS hop, and — worst — **retry backoff**.
48+
49+
## Root causes (code-grounded, ordered by leverage)
50+
51+
1. **Retry-as-readiness is masking a boot race — the acute one.** The recent
52+
commit: *"retry `workspace.active.requested` up to ~60s before crashing."*
53+
`shell/src/App.svelte:375` also backs off 8× on `loadWorkspaces`. That ~60s is
54+
the shell **waiting for a dependency to become ready** (cold service, DB
55+
connection warming, NATS responder not yet registered), not doing work.
56+
Suspected to be most or all of the observed minute.
57+
2. **Cold starts, in series.** One boot call traverses shell → workspace-service
58+
→ NATS → resolver → SurrealDB Cloud. A cold service anywhere on that path
59+
wakes on the request; multiple cold hops compound.
60+
3. **Sequential remote-DB round trips on boot.** Memberships, workspace list,
61+
active workspace, rows — each a separate cross-country round trip to aws-use1
62+
if issued back-to-back.
63+
4. **Cross-service auth on every connect.** Each WS upgrade verifies the JWT and
64+
fetches `/api/me` from id.didi.sh (cached only ~60s, `didi.ts:96`) — and every
65+
remote repeats it.
66+
5. **Per-remote fan-out.** Boot cost multiplies by the number of microfrontends,
67+
each with its own transport + auth + initial capability calls.
68+
6. **NATS request/reply between co-located services** is pure serialization
69+
overhead when there's no concurrency to justify it.
70+
71+
## The thesis
72+
73+
The system is a distributed, multi-tenant-shaped mesh serving **one user**. The
74+
fix is to **right-size the architecture to actual scale** — reserve the mesh for
75+
when concurrency demands it, and until then collapse boundaries so calls are
76+
in-process and boot is deterministic.
77+
78+
## Design space (measure first, then pick)
79+
80+
**Step 0 — MEASURE, don't guess.** Instrument the boot path end to end (WS
81+
upgrade, auth verify, /api/me, workspace.list, workspace.active, per-remote
82+
connect) with timestamps. Confirm the minute is the retry race before
83+
refactoring anything. A [[No-User-Visibility-Into-State-Needs-A-State-Inspector]]
84+
surface / the live/not-live indicator work is the natural home for this.
85+
86+
Then, by leverage:
87+
88+
- **Kill retry-as-readiness.** Make services signal ready and the shell's first
89+
call succeed deterministically (or a fast, bounded wait) — turns 60s into ms.
90+
- **Keep the request-path services warm** (no scale-to-zero; a warm SurrealDB
91+
connection pool). Cheap, ops-level, big.
92+
- **One bootstrap call.** A single `workspace.bootstrap` capability returning
93+
memberships + workspaces + active + initial state, instead of N sequential
94+
DB/NATS round trips.
95+
- **Embed memberships/claims in the JWT** so auth needs zero cross-service
96+
`/api/me` fetch.
97+
- **Share one transport across remotes** (single WS, single auth verification)
98+
instead of per-remote handshakes.
99+
- **Collapse services.** For single-user / small-team scale, fold
100+
resolver + content-ingest + prompt-runner (and possibly the WS gateway) into
101+
fewer processes so NATS request/reply becomes function calls. Reserve split
102+
services for a real concurrency/scale trigger.
103+
- **Optimistic boot.** Render cached workspaces from localStorage instantly,
104+
revalidate in the background — perceived ms regardless of revalidation cost.
105+
106+
## Explicitly NOT this issue
107+
108+
- Not a call to abandon the distributed design permanently — it's a call to
109+
match it to current scale and make the boundaries cheap or absent until scale
110+
arrives.
111+
- Not the auth-persistence / cookie-partitioning bug
112+
([[Workspace-And-Corpora-Connection-Slow-To-Hanging-And-Auth-Wont-Persist]]) —
113+
related surface, different root cause; cross-linked, not merged.
114+
115+
## See also
116+
117+
- [[Workspace-And-Corpora-Connection-Slow-To-Hanging-And-Auth-Wont-Persist]] — the production connection/auth issue on the same surface.
118+
- [[Live-Not-Live-Indicator-Tooling-And-Cross-Service-Error-Surfacing]] · [[No-User-Visibility-Into-State-Needs-A-State-Inspector]] — where boot instrumentation would live.

0 commit comments

Comments
 (0)