Raxx · internal docs

internal · gated ↑ index

ADR 0023 — Render ID Granularity: Per-View vs Per-Component vs Per-Field

Status: Accepted (per-view for MVP; revisit at GA)
Date: 2026-04-29
Deciders: software-architect
Refs: workflow-uuid-tracing.md, ADR-0021


Context

The workflow tracing design introduces a Render ID (rnd_*) stamped on each render of a view to any actor (user, support agent, admin). The Render ID carries the actor identity, the workflow context, and the data-mask state (what was masked for that actor at that moment).

Three granularity choices are available:

  1. Per-view: one Render ID per page load or SSE-pushed state update. A "view" is a named top-level route or modal in Antlers (e.g., trade-entry, backtest-results, positions).
  2. Per-component: one Render ID per React component that renders user data (e.g., PositionRow, BacktestChart, OrderHistory). Multiple Render IDs per page load.
  3. Per-field: one Render ID per data field rendered (e.g., each P&L value, each position quantity). Many Render IDs per page load.

The choice affects event volume, query complexity, support-tool expressivity, and implementation cost.


Decision

Per-view granularity for MVP. Revisit at GA if per-component granularity is needed for support investigations.

Rationale:

Event volume

Per-field is out of scope indefinitely. Per-component is a valid future choice; its costs are acceptable at scale if the support-transparency use case requires it.

Support-utility analysis

The primary support use case is: "what was this user looking at when they placed this trade?" A per-view Render ID answers this question with full fidelity — it identifies the exact screen (e.g., trade-entry) and the data-mask state at that moment.

The secondary use case is: "did the user actually see the position value that was shown?" Per-view granularity does not answer this at the field level. But this question is better answered by the action event stream (if the user submitted a form, the field values are recoverable from the action context) than by a per-field Render ID. Render IDs record what was presented, not what the user read. They are not a substitute for action event context.

Implementation cost

Per-view: a single middleware wrapper on Antlers' route-level API responses. Server-side only. No React changes required.

Per-component: requires either (a) a React context that propagates a render ID through the component tree and flushes Render ID events on component mount, or (b) a server-side component-registry approach. Both require significant frontend instrumentation.

Per-field: would require instrumenting every data binding in Antlers. Not tractable at current frontend scale.

GDPR implications

More Render IDs mean more event rows containing actor_id (a reference to the person who rendered the view). Higher event volume increases the cost of the GDPR pseudonymization job on erasure. Per-view granularity keeps this cost bounded and predictable.


Consequences

Positive

Negative

Migration to per-component (if needed post-GA)

Per-component granularity can be added as a new event type (rnd_component_*) without replacing per-view Render IDs. The per-view event continues to exist; per-component events are additive, emitted only for components that carry sensitive data. This is an additive change with no schema migration required.


Alternatives Considered

Per-component from day one

Would provide richer support-investigation capability. Rejected for MVP because: (a) implementation requires frontend instrumentation; (b) event volume is 10–20× higher, which constrains the SQLite MVP path; (c) the support use cases do not yet require this level of detail. Explicitly deferred, not permanently rejected.

No Render IDs at all

The support transparency use case ("user can see when support viewed their session") requires a record of when support rendered a user's data. Without Render IDs, this is achievable only by instrumenting support API calls — which is a subset of what Render IDs provide. Render IDs are more general; they capture any actor's view of any surface. Rejecting Render IDs entirely would mean support-presence tracking is a separate, fragile implementation. Rejected.

Render IDs only for support/admin actors, not for users viewing their own data

A simpler scope: only emit Render IDs when a non-user actor renders a user's data. This reduces event volume but eliminates the ability to replay what the user themselves saw at a given moment. The replay use case ("what did I see 5 minutes before this trade?") requires Render IDs for the user's own renders. Rejected.