The spinner mirrored the service map

P6X4's concurrent page was technically fast and visually fragmented because every backend boundary became its own loading state.

P6X4's new document page began rendering in less than half the previous server wait. It also showed six loading indicators.

The page frame arrived first. Document identity had a skeleton, policy had a spinner, rendering status pulsed, search suggestions shimmered, audit history showed placeholder rows, and delivery actions waited behind another fallback.

The boundaries matched the architecture precisely.

That was the defect.

The person reading the page did not have six tasks. They wanted to identify a document, understand its current state, and perhaps take one safe action. I had exposed the service and query map as visual choreography.

Faster bytes produced slower comprehension

The previous implementation waited for all route data before sending useful content. Its first meaningful paint was late but coherent. The streaming version returned a shell quickly and revealed regions as each dependency resolved.

I measured both with synthetic latency:

  • Response start improved.
  • Stable document identity appeared slightly earlier.
  • Final completion was similar.
  • Layout shifted more in the streaming version.
  • The primary action changed availability twice.
  • Readers in a small keyboard test paused more often before acting.

One timing metric had improved while the task became harder to parse.

I stopped asking only when content arrived and added two questions: when could a person recognize the page, and when could they trust the next action?

The skeleton lied about structure

The document identity skeleton used three generic grey bars. The final region contained a title, revision badge, owner label, and status message. Its height varied with the title, so replacement moved everything below.

Worse, the placeholder implied that unknown text was being fetched when the route already knew the document ID and could load its primary revision quickly. I had wrapped the region because its component made one slow secondary query.

I split data by authority. The initial frame loaded stable identity and current revision. Optional ownership detail arrived later inside a smaller region. The fallback preserved the label and geometry of that region rather than replacing the entire header.

A skeleton is not neutral. It makes a claim about what structure exists and what information is unavailable.

A spinner communicates activity and little else. Six spinners made it impossible to know which content was required, whether any had failed, and when the page was usable.

I categorized waits:

  • Required to identify the document.
  • Required before a consequential action.
  • Secondary evidence that could arrive later.
  • Optional enhancement whose absence did not block the task.
  • Durable background work that should not depend on the page staying open.

Only the first two influenced primary readiness. Secondary regions received labelled, stable pending states after a perceptual delay. Optional enhancements occupied reserved space only when their appearance would otherwise shift content. Durable work showed its workflow state, not an indefinite local spinner.

The number of indicators fell because several waits no longer deserved individual visual events.

Query boundaries were not comprehension boundaries

Audit history came from two queries: immutable decision facts and related effect receipts. I placed a Suspense boundary around each because they could resolve independently.

Readers understood them as one evidence timeline. Revealing half created a misleading chronology: a delivery completion could appear before the document decision that caused it.

I composed the queries behind one evidence-region boundary, normalized their ordering by domain sequence and causation, and revealed the coherent timeline together. The region could take slightly longer to appear. What appeared was interpretable.

Search suggestions and document identity had the opposite relationship. Suggestions could fail or lag without weakening identity, so they remained isolated.

The useful boundary followed what could be understood independently, not what could be fetched independently.

The primary action needed stable authority

The delivery button first rendered disabled, became enabled after document state arrived, became disabled when policy loaded, then reappeared after a newer policy response. Every state was defensible from the data available at that instant. The sequence was unacceptable.

I defined the action region's prerequisite view: current document revision, current authority decision, existing delivery intent if any, and adapter capability. The region did not reveal an actionable control until that view was coherent.

While it loaded, the page could still show document content. A labelled “Checking delivery availability” message appeared only after a delay. If authority failed, the region explained that actions were unavailable without erasing the document.

Streaming did not justify offering a button based on partial truth.

The first page showed “Loading renderer,” “Loading delivery service,” and “Loading index.” Those labels described implementation.

I rewrote states around the task:

  • “Preparing this revision” for an accepted render intent.
  • “Checking delivery status” for evidence reconciliation.
  • “Recent changes may not appear in search yet” for projection lag.
  • “Evidence history is unavailable” for a local read failure.

The language remained specific without teaching the service map. It also survived P6X4's consolidation; the same product state applied whether work ran in another service or another process from the same artifact.

Architecture changes more frequently than user intent. Interface vocabulary should prefer the latter.

A fallback had a time policy

Immediate fallback display caused flicker on fast transitions. Waiting too long made a slow region appear inert.

I gave each product region a policy:

  • Preserve previous truthful content during a short transition.
  • Show a local pending label after a tested threshold.
  • Escalate longer waits with an explanation and available alternatives.
  • Replace pending with a durable workflow state when work had been accepted.
  • Never reset accepted work because the component remounted.

The exact durations were tuned under synthetic latency and were not presented as universal human-factors constants. The important part was that visual feedback depended on consequence and elapsed perception, not the first microtask in which React reported pending.

The page became quieter without becoming unresponsive.

Previous content needed honest labelling

Transitions allowed the old result or route region to remain visible while the new one prepared. This preserved continuity and risked showing stale content under fresh controls.

For search, the result summary named the query it represented until the new results settled. For document navigation, the old document identity did not remain under the new URL. The stable outer layout persisted, while the identity region switched only when the new route's authoritative frame was ready.

I avoided global opacity as a stale-state signal. It reduced contrast and did not explain what was behind. A small labelled relationship was more accessible and precise.

Continuity was useful only while the interface admitted which state it continued to show.

Generic skeletons used arbitrary heights. I measured the final regions across short and long titles, empty and populated histories, narrow and wide viewports, and large text settings.

For content whose height was bounded, the fallback reserved the minimum stable structure: heading, status line, and a region frame. For unbounded evidence lists, I did not reserve the eventual full height. The region began below the primary task so its expansion did not move controls a person was about to activate.

Responsive order mattered. On a narrow screen, delivery actions appeared before optional related documents regardless of which data resolved first. CSS layout and DOM order followed task priority, not response timing.

Preventing movement was not only a performance score exercise. It protected focus, pointing, and reading position.

Accessibility exposed invisible fragmentation

Each fallback had role="status", creating a flood of announcements as regions arrived. The visual page looked busy; the spoken page was worse.

I reduced live regions to a route-level summary and consequential local updates. Loading placeholders did not announce decorative changes. Settled search count announced politely after input paused. Accepted render and delivery states used their durable workflow messages.

Headings and landmarks existed from the initial frame and did not disappear during replacement. Focus stayed with the initiating control or moved according to navigation semantics, never to whichever region resolved first.

I tested with keyboard navigation, a screen reader, reduced motion, zoom, slow JavaScript, and server errors. The fragmented architecture had been audible even when CSS made it attractive.

One Suspense data source rejected outside the expected error boundary. Its spinner remained while an error appeared only in logs.

Every pending region gained a corresponding failure and empty state. A deadline transformed an unbounded wait into a recoverable state; it did not assume the underlying operation had failed. For durable workflows, the page queried authoritative status after transport timeout.

The evidence region could offer Retry because its read was safe. Delivery could offer Query status or open recovery depending on adapter capability. A generic fallback could not choose those actions.

Loading and error boundaries were designed together around the same product consequence.

Streaming priorities followed the first useful task

I ordered server work around a route contract:

  1. Resolve disclosure-safe route identity and authorization.
  2. Load current document revision and stable task navigation.
  3. Determine coherent primary action availability.
  4. Stream evidence history.
  5. Stream optional related documents.

The order was not identical to query speed. A fast recommendations query did not earn a place in the first response ahead of document authority. Where independent work could start concurrently without withholding the frame, it did. Revelation still followed meaning.

This improved the first useful moment even when total completion changed little.

Caches could produce out-of-order freshness

The document header came from authority while an action panel briefly used a cached policy projection. The panel arrived faster and contradicted the header's current revision.

I attached source revision and policy revision to region data. Components that jointly authorized an action had to share a compatible evidence boundary. Optional regions could display older projections when labelled and safe.

A cache hit was not inherently preferable to a slower current answer. The loading design accounted for freshness, not merely latency.

This connected interface streaming to P6X4's data classification: authority, snapshot, projection, and cache should not reveal themselves in an order that implies equal truth.

A final screenshot could look excellent while the path to it flickered, shifted, or contradicted itself.

The scenario suite recorded frames and accessibility state at controlled checkpoints:

  • Initial server bytes.
  • Stable document frame.
  • Delayed action prerequisites.
  • Evidence success or failure.
  • Optional recommendation arrival.
  • Navigation during an unresolved region.
  • Worker state changing after the page opened.

Assertions checked heading continuity, action availability, focus, announcements, layout geometry, source revisions, and durable status.

I still inspected screenshots at narrow and wide widths. The temporal sequence became the primary artifact.

Backend consolidation did not automatically calm the page

P6X4's architecture had already moved several services into modules. The UI remained fragmented because its component and data boundaries preserved the old map.

This was an important correction. Architectural subtraction does not reach users automatically. Query hooks, loading components, error copy, and page layout can continue teaching a topology that no longer exists.

I removed obsolete client abstractions, composed related reads behind product views, and renamed states according to domain meaning. The page changed only after the interface architecture changed too.

The service map had survived in spinners.

The final route did not return to waiting for everything.

Document identity and primary revision arrived first. The action region appeared when its authority view was coherent. Evidence streamed as one interpretable timeline. Optional suggestions arrived last and failed locally. Durable render or delivery work persisted independently of the page.

There were fewer placeholders and more useful content sooner. The interface did not narrate every dependency resolution.

Performance remained measurable: bytes started early, client work stayed bounded, layout movement fell, and the task became possible before optional completion. The qualitative improvement appeared in the ability to explain what was ready at each moment.

A loading state is part of the model

I had treated fallbacks as temporary decoration around the real interface. They occupy a large share of experience under slow networks, cold caches, failures, and background work.

Every fallback makes claims:

  • What region exists.
  • What is already known.
  • What remains uncertain.
  • Whether previous content is still valid.
  • Which actions are safe.
  • What happens if the wait continues.

Those claims deserve the same design care as completed content.

The original page mirrored P6X4's service map because service boundaries were the easiest places to put Suspense. The revised page mirrored the person's task because comprehension was the harder boundary to design.

The faster page stopped looking like six systems waking up. It began as one document becoming understandable.

That standard stayed useful after the measurements ended: every new fallback had to explain which independent user concept it protected, not merely which promise happened to suspend.

Rapidly selecting several documents created overlapping route work. An older response could arrive after a newer selection and briefly replace the frame.

The router and renderer could cancel or abandon obsolete preparation, but I still guarded the product state with navigation identity. Results applied only to the current destination and source revision. Server logs linked abandoned work to its originating navigation without reporting it as a user-visible failure.

This was safe because document reads were interruptible. A delivery command initiated from a route used a different durable intent and continued even if navigation changed. The page did not conflate “this render is no longer needed” with “this external action is cancelled.”

Keeping navigation and effect identities separate prevented concurrent UI behavior from leaking into workflow semantics.

Empty states did not pass through loading

An evidence timeline with no entries initially showed three skeleton rows and then “No evidence yet.” The sequence implied content had disappeared.

When the server could know emptiness with the primary query, it returned the empty state in the initial frame. When emptiness depended on a slower region, the fallback described the region without predicting rows. “Loading evidence history” became “Evidence history” with a modest pending indicator, then the final empty explanation.

Empty was a valid result, not the absence of a successful load. Designing it alongside pending and error reduced another form of visual surprise.

Reduced motion changed more than animation

Disabling shimmer removed movement but left six blocks repeatedly changing contrast as state updated. I replaced animation-heavy placeholders with stable region frames and text. Progress did not depend on pulsing opacity.

For long durable work, no indeterminate animation ran forever. A timestamp, current phase, last evidence, and next check communicated progress more truthfully. Updates used polite announcements only when the state meaningfully changed.

The reduced-motion test improved the default design. Motion had been compensating for fallbacks that lacked information.

On desktop, optional suggestions sat beside the document and their late arrival caused a modest shift. On a narrow viewport, they appeared above delivery actions because CSS source order followed the original service-component layout.

I rewrote DOM order around task priority and used layout rules to place secondary regions beside primary content only when space allowed. The reading and focus order stayed document, status, safe actions, evidence, then suggestions.

Streaming order could not override that sequence. If suggestions resolved first, their bytes could wait to reveal until the preceding structure existed. Network readiness was not content priority.

Visual regressions needed temporal fixtures

Static screenshot tools captured the final route and missed most failures. I added deterministic delay controls to each region and captured a small filmstrip at fixed milestones. The fixture named the state rather than sleeping for arbitrary time.

Comparisons looked for geometry, unexpected affordances, missing headings, and duplicate status indicators. The same fixtures fed keyboard and accessibility checks. A failure report showed the sequence leading to the incorrect final state.

This made loading design reviewable in ordinary changes. A developer convenience refactor could no longer add a fallback to every query without visibly fragmenting the filmstrip.