design: two-runtime compute read isolation - #38239
Open
antiguru wants to merge 6 commits into
Open
Conversation
antiguru
added a commit
to antiguru/materialize
that referenced
this pull request
Aug 17, 2026
The design of record, the evaluation record and the two machine-checked protocol models land separately in MaterializeInc#38239, along with their CI checks. They have no dependency on this code and reviewing 4,700 lines of prose against 7,000 lines of compute is worse for both. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019G29DBfgE8LXpE5jamm2Zi
The design of record for isolating reads from index maintenance inside a compute replica, plus the two machine-checked protocol models and the experiment record behind it. `design.md` opens with the decomposition that shaped everything else: twelve reported symptoms, the mechanisms behind them, and which of sixteen candidate solutions reaches each. Every cell carries an evidence label, and the table deliberately includes mechanisms nothing here addresses, because a decomposition listing only the causes we have answers for is not a decomposition. Two of the widest-blast-radius mechanisms are among the unaddressed. `evaluation.md` records the experiments with their fixtures and venues. Several retired claims the design started with. The offload alone captures the peek-tail win, so the second runtime is not what removes head-of-line blocking between peeks. The offload is measurably worse than doing nothing when a peek queues behind a long operator activation. And the second runtime's case is temporary dataflows and introspection during hydration, not peeks at all. `peek-placement.md` parks the peek-substrate question as orthogonal, with the deciding experiment and its rule registered in advance rather than settled by implementing every candidate and learning afterwards. The models are checked in CI, because a model nobody runs reads as assurance without being any. `protocol-holds/` is TLA+ over the read-hold protocol and runs three configs: the shipped design, plus two that are expected to violate the invariant and whose passing would mean the model can no longer express the defect the design fixes. It earned its place by refuting broadcast-alone before that was implemented. `protocol/` is a Lean development of the command-ordering argument. `check-copyright.sh` gains an exemption for `lean-toolchain`, which is a version pin with nowhere to put a header. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019G29DBfgE8LXpE5jamm2Zi
antiguru
added a commit
to antiguru/materialize
that referenced
this pull request
Aug 21, 2026
The design of record, the evaluation record and the two machine-checked protocol models land separately in MaterializeInc#38239, along with their CI checks. They have no dependency on this code and reviewing 4,700 lines of prose against 7,000 lines of compute is worse for both. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019G29DBfgE8LXpE5jamm2Zi
antiguru
force-pushed
the
mh/two-runtime-design
branch
from
August 21, 2026 07:39
c6e43ec to
bd6bfb6
Compare
The directory held seven documents, three of which covered the read-hold mechanism and two of which were spent scaffolding. It now holds one design document that targets the interactive runtime. The protocol section described the wrong mechanism. It specified capping the compaction frontier at the multiplexer, which the implementation replaced with broadcast compaction and a standing hold per shared collection. That section is rewritten from `broadcast-compaction.md`, including the counterexample that rules out broadcasting without the hold and the liveness coupling the hold introduces. The cap, the synthesized `AcquireHolds` command, and the in-process sequence barrier are recorded as rejected alternatives, with the reason each failed: the cap failed at its retirement point rather than at the cap, since `send` carries no ack. Both model checks are removed, along with their CI jobs and images. The TLA+ spec modelled the shipped mechanism and the Lean model did not: its scope was the controller's read hold and the multiplexer's cap, and both of its counterexamples target behaviours no longer present in any form. The reasoning each contributed survives as prose in the rejected alternatives. Peek placement becomes an orthogonal axis discussed once rather than an argument threaded through the document. The solution matrix keeps its row, because the comparison is what bounds the interactive runtime's claims, but the adjudication between placement candidates, the substrate follow-ups and the routing policy move to the tracking issues. `peek-placement.md` and `peek-offload-stash-plan.md` move to the branch that implements the offload. The experimental evaluation moves to a project document. Evaluation artifacts do not belong in a design, and the document also carried experiment protocol for arms the code no longer reaches the same way. Also corrected: the serving path claimed walking off the worker was abandoned, the arrangement-size doubling is recorded as not reproducing on staging, and the open findings drop the items describing deleted code.
The document described the branch as it stood before the implementation was split into reviewable layers, and three parts of it no longer matched the code. Peek execution shipped separately. The summary and the placement section said peek offloading was parked pending an experiment; it now records that the walk runs in budgeted slices with offload past the budget, that both are dyncfgs, and that the interactive runtime inherits that path. The serving path section replaces the runtime's own pending-peek variant with the unified `IndexPeek` over `IndexTraces`, and the registry section describes how a shared peek parks in `pending_work` until its target's dirty mark. Two open findings were fixed and are documented as mechanism rather than kept as defects. The reader's handle mirrors `TraceAgent`: it joins on set, reports the join, and seeds its physical hold at the chain coverage, so the inert physical hold finding is removed and the compaction section explains why the coverage is the only correct seed. The import keeps no separate hold pinned at `as_of`; the read hold is the returned arrangement's own trace handle, so the frozen-hold section becomes a description of the feedback path. Re-exports are aliases. The registry section replaces the sentence about sharing an `Arc` under a new id with the alias mechanism: `publish_alias`, its refusal when a reader bound first and the import-based fallback that covers it, the target-governed frontiers, and the meet over aliases after the target drops. The discarded-failure finding is removed and the measured cost of the earlier import-based publication is recorded. The multiplexer, configuration and testing sections are updated to the shipped routing predicate, the soft assertion on transient imports, the CI variable system parameter, the four driver specs, the sqllogictest, the feature and parallel benchmark scenarios, and the swap scenarios, with the numbers one nightly run produced. The implementation history lists the stacked pull requests. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VDm7opomJLxbNUEP3r9BLk
The shared import follows the dataflow's `until` instead of synthesising a bound one step past `as_of`, so the section that presented the bound as a call-site narrowing now places the single-time restriction where it lives, in the routing predicate. An export whose arrangement is an imported shared arrangement aliases its publication point instead of hitting an `unreachable!`, which closes that open finding and adds a fifth driver spec. The interactive runtime installs no logging dataflow, so the runtime tells the peer's publications apart by whether it hosts the collection rather than by transience, and the multiplexer's frontier filter is described as a guard on that invariant rather than as a repair for empty copies. The registry's state sits behind one lock. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VDm7opomJLxbNUEP3r9BLk
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VDm7opomJLxbNUEP3r9BLk
The sharing primitive became `SharedSpine`, a `Trace` wrapper that mirrors the spine's chain and frontiers into the publication point inside each mutation. The design records why a spine behind a mutex was rejected, with the measured reader and writer latencies, replaces the sink-based feed and compaction sections, drops the forwarded controller frontier, and marks the arrangement-size doubling as gone with the sink. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VDm7opomJLxbNUEP3r9BLk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
A compute replica maintains indexes and serves reads on the same timely workers, and timely does not preempt a running task. So a read waits behind maintenance work, not because the machine is out of CPU but because the one run loop is busy and cannot be interrupted. The sharpest form is introspection:
mz_introspectiondescribes a replica's own state and cannot be served from any other replica, so it is unavailable exactly when an operator needs it.This is design only. No production code. It is the design of record for the implementation stack, #38386 through #38393, with the benchmarks in #38676 and #38678, and it describes what those pull requests ship.
Description
One document,
design.md. It targets the interactive runtime: a second in-process timely runtime that renders temporary dataflows and serves reads off the maintenance runtime's arrangements, zero-copy through a per-process sharing registry.It opens with the decomposition that shaped everything else: twelve reported symptoms, the mechanisms behind them, and which of sixteen candidate solutions reaches each. Every cell carries an evidence label distinguishing measured from argued from read-off-the-code, and the table deliberately includes mechanisms nothing here addresses. Two of the widest-blast-radius ones are among those, which is the point: a decomposition listing only the causes we have answers for is not a decomposition.
Several claims the work started with are retired in it:
Peek placement is therefore treated as an orthogonal axis and discussed once. It needs no second runtime and this design needs none of it. It shipped separately, as budgeted peek slices on the worker with offload past the budget, and #38449 is its design. The interactive runtime inherits that path unchanged.
The protocol section describes what shipped: broadcast compaction and a standing hold per shared collection, including the counterexample that rules out broadcasting without the hold and the liveness coupling the hold introduces. Capping the frontier at the multiplexer, a synthesized
AcquireHoldscommand, and an in-process sequence barrier are recorded as rejected alternatives with the reason each failed.What the current revision changed
The document now matches the stacked implementation rather than the branch it was split from.
TraceAgent(join on set, physical hold seeded at the chain coverage), and the import keeps no hold pinned atas_of, so a long-lived importer's compaction feeds back to the publisher.IndexPeekpath, with the trace provenance as the only difference.What moved out
The experimental evaluation is a project document under Interactive read isolation, which also tracks the work as issues. Evaluation artifacts do not belong in a design.
Both model checks are removed with their CI jobs. The TLA+ spec modelled the shipped mechanism; the Lean model's scope was the controller's read hold and the multiplexer's cap, and both of its counterexamples target behaviours no longer present in any form. The reasoning each contributed survives as prose in the rejected alternatives.
🤖 Generated with Claude Code
https://claude.ai/code/session_01VDm7opomJLxbNUEP3r9BLk