docs: clarify the ALTER CLUSTER graceful-resize default and system clusters - #38202
Draft
claude[bot] wants to merge 4 commits into
Draft
docs: clarify the ALTER CLUSTER graceful-resize default and system clusters#38202claude[bot] wants to merge 4 commits into
claude[bot] wants to merge 4 commits into
Conversation
…usters User feedback relayed internally reported three points of confusion on the ALTER CLUSTER page: whether a bare resize is graceful, whether the feature is still private preview, and whether system clusters behave like user clusters. All three trace to specific text on the page. The SIZE syntax element carried a warning that "changing the size of a cluster may incur downtime", which is the first thing a reader sees and which contradicted the Resizing section further down. It now states the graceful default and that no WITH option is needed to get it. The default is now stated up front, along with the distinction that caused the confusion: WAIT UNTIL READY does not enable graceful resizing and is not required for it. Since v26.35 a bare resize is already graceful and already returns immediately, and the WAIT options only set the deadline and the action taken if the deadline passes. The timeout options move under their own "Customizing the timeout" heading so the default and its customization are no longer interleaved. A bare, unlabeled private-preview badge sat on the legacy section heading, where it read as marking zero-downtime resizing as a whole. It is removed. The labeled badge scoped to the WAIT UNTIL READY and WAIT FOR options is kept, since those options remain gated. A new "System clusters" section records that a bare resize of a system cluster did not take the graceful path before v26.38, while an explicit WAIT UNTIL READY was honored, and points at the option as the workaround on earlier versions. The self-managed troubleshooting guide's mz_catalog_server resize walkthrough asserted graceful behavior unconditionally, which does not hold on any currently released version, so it gets the same version qualification rather than losing the guidance. Also fixes a "REPLICATON FACTOR" typo and a SET (SIZE '100cc') example missing its equals sign. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QmPn2Y26AykL19ZkKXLXLY
The blocking boundary this page carried was off by one release, and it collapsed the system-cluster case into the user-cluster one. Non-blocking behavior for user clusters landed in v26.34.0, not v26.35: enable_cluster_controller and enable_background_alter_cluster are both false in the v26.34.0-rc.1 tag and both true in v26.34.0-rc.2 and in the released v26.34.0 tag. Blocking was therefore the behavior in v26.33.x and earlier, so the legacy section and its explicit anchor are retitled to v26.33 and earlier and the sentence about WAIT UNTIL READY holding the session open now names v26.33. System clusters are a carve-out. From v26.34.0 through v26.37.0 the routing gate was ENABLE_CLUSTER_CONTROLLER.get(...) && cluster_id.is_user(), so a system cluster fell to the legacy machine, where an explicit WAIT UNTIL READY was both the only way to get a graceful resize and blocking. The System clusters warning now states that, and the self-managed troubleshooting walkthrough says the same about the statement it recommends. The graceful-by-default text keeps its pre-existing v26.35 number. The code default flipped in v26.34.0, but enable_background_alter_cluster is LaunchDarkly-synced, so the cloud-visible boundary can legitimately differ and this repo cannot settle which number users should see. That discrepancy is recorded as an open question on the pull request instead of being resolved here. Also notes that WITH (WAIT ...) is gated behind the enable_zero_downtime_cluster_reconfiguration session feature flag, whose compiled-in default is false, so on a default self-managed deployment the option errors rather than resizing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QmPn2Y26AykL19ZkKXLXLY
The page stated a single version, v26.35, for the graceful `ALTER CLUSTER` resize default. Cloud and Self-Managed genuinely diverge here, so one number is wrong for one of the two audiences. The compiled default flipped in v26.34.0: enable_cluster_controller and enable_background_alter_cluster are both false in the v26.34.0-rc.1 tag and both true in v26.34.0-rc.2 and in the released v26.34.0 tag. That release shipped with SQL-530 though, where graceful reconfiguration deadlocked on any cluster hosting a single-replica Postgres, MySQL, or SQL Server source and then rolled back at its deadline without resizing. The fix (#37740) merged 14 minutes after the v26.34.0 tag was cut, so it missed that release entirely. The first tag carrying the fix is v26.34.1, whose release notes announce asynchronous cluster reconfiguration and are explicitly marked Self-Managed only. Cloud never ran a fixed v26.34 and first got the behavior with v26.35.0, which is where the same feature is announced for Cloud. Hence v26.34.1 for Self-Managed and v26.35 for Cloud. The version moves out of the heading, since the heading can no longer carry a single number, and into a sentence naming both. No page linked the old heading's generated anchor, so nothing dangles. The blocking boundary is unchanged: non-blocking arrived in v26.34.0 for both deployment types, so v26.33 and earlier remains correct for the session-blocking behavior.
Resolve the conflict in doc/user/content/sql/alter-cluster.md and refresh the factual claims against current main. Upstream removed the private-preview labels from the ALTER CLUSTER page and rewrote the WAIT FOR bullet to describe the new rollback-on-timeout behavior. Both are taken as-is. Our removal of the bare private-preview badge converged with upstream's, so it is not duplicated. Our heading rename and the new System clusters section are re-applied on top. Upstream also removed the enable_zero_downtime_cluster_reconfiguration feature flag, so WITH (WAIT ...) is now accepted unconditionally. The paragraph claiming the options are gated behind that flag no longer matches the code and is dropped. The self-managed troubleshooting note keeps the flag mention, scoped explicitly to v26.37 and earlier, where the gate did apply. v26.38 has shipped, so the graceful system-cluster resize is stated as plain fact rather than as an upcoming change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QmPn2Y26AykL19ZkKXLXLY
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.
Requested by Tyler Hartwig · Slack thread
Motivation
User feedback relayed internally reported that the
ALTER CLUSTER/WAIT UNTIL READYdocs are confusing on three points:mz_catalog_server,mz_system,mz_probe,mz_support,mz_analytics) behave differentlyfrom user clusters.
ALTER CLUSTERbehavior are hard to tell apart, as is what isGA versus private preview.
resize.
All three trace to specific text, and each one checks out against the code:
SIZEsyntax element indoc/user/data/examples/alter_cluster.ymlcarried a warning that "changing the size of a cluster may incur
downtime". That is the first thing a reader sees when looking up how to
resize, and it directly contradicted the Resizing section on the same page,
which says a resize incurs no downtime.
{{< private-preview />}}sat on the legacy sectionheading, where it reads as marking zero-downtime resizing as a whole rather
than the option it was meant to scope.
doc/user/said anything about howALTER CLUSTERtreats systemclusters, while the self-managed troubleshooting guide asserted graceful
resizing of
mz_catalog_serverunconditionally. That assertion does not holdon any currently released version.
Description
Before / After (what a reader of the docs page sees):
SIZEoption,ALTER CLUSTERsyntax table. Before: a warning thatchanging a cluster's size "may incur downtime". After: a note that resizing
is graceful and incurs no downtime by default, that no
WITHoption isneeded to get that, and a pointer to the system-cluster caveat.
Resizing, current behavior. Before: an H4 titled "Downtime
considerations for v26.35 or after", whose body opened with unformatted
ALTER CLUSTER <name> SET (SIZE = ...), and which interleaved the defaultbehavior with the timeout options. After: "Resizing is graceful by default",
with the version stated in the body as v26.35 on Cloud and v26.34.1 on
Self-Managed rather than in the heading, stating plainly that this is the
default and that
WAIT UNTIL READYis not required for a zero-downtime resize, that thestatement returns immediately, and that the default deadline is 24 hours with
a rollback if the new replicas have not hydrated by then.
The distinction at the heart of the confusion. Before: the page implied
that customizing the timeout is what gets you the graceful path. After: the
page says the
WAIToptions do not enable graceful resizing and are notrequired for it, and that their only effect is to set the deadline and choose
what happens when it passes. The timeout options move under their own
"Customizing the timeout" heading, so the default and its customization are
no longer interleaved. It also records that the
WAIToptions still returnimmediately and do not hold the session open, which is the part that changed
from the blocking behavior of v26.33 and earlier.
Preview badges. Before: two badges, one labeled and scoped to the timeout
options, one bare and unlabeled on the legacy heading. After: only the
labeled one, still scoped to
WAIT UNTIL READY/WAIT FOR. The legacyheading is retitled "Resizing in v26.33 and earlier", which is what it is
actually about.
System clusters. Before: nothing. After: a "System clusters" section
saying
ALTER CLUSTER ... SET (SIZE = ...)applies to system clusters too,and a warning that a bare resize of one did not take the graceful path before
v26.38, while an explicit
WAIT UNTIL READYwas honored and blocked thesession, with the option shown as the workaround on earlier versions.
Self-managed troubleshooting. Before: the
mz_catalog_serverresizewalkthrough stated unconditionally that the resize is a graceful
reconfiguration. After: the same guidance, qualified by version, with the
WAIT UNTIL READYspelling given for v26.37 and earlier. The walkthrough iskept rather than removed, since resizing
mz_catalog_serveris still theright fix for an unresponsive Console.
How. Three files, docs only.
doc/user/data/examples/alter_cluster.ymlholds the rendered syntax tables, so the
SIZEwarning lives there rather thanin the page. The
Resizing process,Monitoring a resizeandCancel a resizesub-headings are left untouched, because#resizing-processand#monitoring-a-resizeare linked from other pages. The retitled legacy headingcarries an explicit
{#resizing-in-v2633-and-earlier}anchor, since theversion number's period makes the generated ID non-obvious.
Two drive-by fixes in text already being edited: a
REPLICATON FACTORtypo,and a
SET (SIZE '100cc')example missing its equals sign.Verification
mainthat a bareALTER CLUSTER c SET (SIZE = ...)is graceful and ungated. The plannerproduces
AlterClusterPlanStrategy::None(
src/sql/src/plan/statement/ddl.rs), a shape change is still reshaped intoa durable reconfiguration record, and the record's defaults for a statement
with no
WITHclause areDEFAULT_CLUSTER_RECONFIGURATION_TIMEOUT(24h) andOnTimeoutAction::Rollback(
src/adapter/src/coord/sequencer/inner/cluster.rs). The feature-flag checkfor
enable_zero_downtime_cluster_reconfigurationruns only when a strategywas given, so the default path is not gated but the
WAIToptions are, whichis why the labeled badge stays.
WAIToptions no longer block. The immediate return isgated on the
enable_background_alter_clusterdyncfg (default on) and not onthe strategy, and the only producer of
NeedsFinalization::Yesisunreachable while the controller owns every managed cluster. An earlier draft
of this PR claimed the options still block; that was wrong and is corrected.
which dropped the three
is_user()conjuncts and records the behavior changeas a bare
ALTER CLUSTER mz_system SET (SIZE ...)going "from a synchronouswhole-set recreation to a background graceful reconfiguration", noting that
"the graceful path did not exist for system clusters before".
doc/user/data/examples/alter_cluster.ymlstill parses. TheSIZEdescription is a plain (unquoted) multiline YAML scalar, so a
": "in thenew prose broke the document mid-edit; the wording avoids the colon rather
than restructuring the scalar, which keeps the existing folding behavior.
alter-cluster.md, including the linksrendered onto it from the YAML data file. All resolve, including the two new
headings and the explicit legacy anchor.
the release notes.
enable_cluster_controllerandenable_background_alter_clusterare bothfalseinv26.34.0-rc.1and bothtrueinv26.34.0-rc.2and releasedv26.34.0, so the compiled defaultflipped in v26.34.0.
v26.34.0nonetheless shipped without the SQL-530 fix(storage/adapter: fix graceful cluster reconfiguration for clusters with single-replica sources #37740), which merged 2026-07-20T16:12:12Z, 14 minutes after the
v26.34.0tag at 2026-07-20T15:58:00Z. The fix is present from
v26.34.1onward,verified by
Instance::get_active_replicas_for_objectinsrc/storage-controller/src/instance.rsstill carrying the oldingestion-export-only branch in
v26.34.0and the rewrittenactive_replica_idsmatch inv26.34.1.v26.34.1announcesasynchronous cluster reconfiguration under an explicit
"Materialize Self-Managed only" marker and lists the single-replica-source
deadlock among its bug fixes,
v26.34.0never mentions the feature at all,and
v26.35.0announces it with a Cloud release date._index.mdgivesv26.34.1a Self-Managed line and no Cloud line.markdown and YAML only and add no new shortcodes, only existing
note,warningandprivate-previewinvocations.Open questions
RESOLVED: the release that carries adapter: let the cluster controller own system clusters #38102 is v26.38, now confirmed against
a real tag.
v26.38.0-rc.1was tagged 2026-08-14T02:59:14Z, after thisPR's earlier checks found no
v26.38.*tag at all, and it does carryadapter: let the cluster controller own system clusters #38102. The routing gate is the evidence:
src/adapter/src/coord/cluster_controller.rsfilters with.filter(|c| c.is_managed() && c.id.is_user())inv26.37.0and with.filter(|c| c.is_managed())inv26.38.0-rc.1, whose module comment reads"The controller owns the replica set of every managed cluster, user and system
alike."
enable_cluster_controlleris also gone fromsrc/adapter-types/src/dyncfgs.rsin that tag, so the controller isunconditional there rather than flag-gated. The v26.38 number in these
edits is therefore confirmed rather than predicted. Note that v26.38.0 final
is not out yet:
doc/user/content/releases/v26.38.mdstill carriesreleased: falsewith date 2026-08-19.STILL OPEN: whether graceful resizing should carry a private-preview badge
at all. This is a PM decision and is deliberately not resolved here beyond
removing the unlabeled badge. What the code says is unchanged: the graceful
default is ungated, while
WAIT UNTIL READYandWAIT FORstill requireenable_zero_downtime_cluster_reconfiguration, whose compiled-in default isfalse. So the badge is arguably stale for the behavior and accurate for theoptions, which is the split this PR encodes.
One factual correction to an earlier note on this item: that flag does have
a LaunchDarkly flag. It sits in
INTENTIONAL_LD_OVERRIDES(
test/launchdarkly-flag-consistency/mzcompose.py:505), the list ofparameters whose "production LaunchDarkly value is deliberately different
from the compiled-in default", not in
KNOWN_MISSING_FROM_LD. That answersthe sub-question of how it comes to be enabled where
WAIT UNTIL READYdemonstrably works: LaunchDarkly serves it on in cloud, which is also why a
self-managed deployment has to enable it by hand. The badge decision itself
remains for a PM.
RESOLVED: the system-cluster divergence was accidental. The author of
adapter: let the cluster controller own system clusters #38102 confirmed it directly: the divergence "was an accident of how we
incrementally developed and then rolled it out." It was not a policy that
system clusters should behave differently. That matches adapter: let the cluster controller own system clusters #38102's mechanical
reasoning recorded earlier in this PR: the exclusion was load-bearing only
because the boot-time builtin replica migration and the controller would
otherwise have been two conflicting writers of one replica set, a conflict
adapter: make a builtin cluster's config own its replica set #37929 removed. Both pages were re-read against this: they state only what
each version does, and nothing frames the difference as intended or as a
property system clusters are supposed to have.
Not addressed here, suggested as follow-ups.
reference/system-clusters.mdlists per-cluster characteristics but says nothing about resizing, and omits
mz_analyticsentirely. adapter: let the cluster controller own system clusters #38102 is inv26.38.0-rc.1, so the v26.38 releasenotes need an entry covering the system-cluster change. Separately,
alter-cluster.mdcarries a pre-existing em-dash in the legacy section("cause a rollback — no size change will take effect"), which is already on
mainand is left alone here to keep this diff scoped.RESOLVED: v26.35 on Cloud and v26.34.1 on Self-Managed, and the page now
says both. A maintainer supplied the missing history from two directions:
a LaunchDarkly flag was disabled 2026-07-24 over a bug and re-enabled
2026-07-31 after the fix, and the bug "was about hydration checks for
single replica sources."
That second detail identifies the bug exactly. It is SQL-530, fixed by
storage/adapter: fix graceful cluster reconfiguration for clusters with single-replica sources #37740, "storage/adapter: fix graceful cluster reconfiguration for
clusters with single-replica sources": the readiness check gated cut-over on
every ingestion reporting hydrated on the pending replicas, but a
single-replica source stays on the replica it already runs on and is never
placed on a pending replica until cut-over, so it could never report hydrated
there and the reconfiguration deadlocked until its deadline, then rolled back
without resizing. The fix skips off-target ingestions in
collections_hydrated_on_replicasand additionally requires pending replicasto be online before cut-over, on both the legacy foreground path and the
controller-owned path.
The dates, all UTC:
v26.33.0tagv26.33.1tag_index.mdv26.34.0-rc.1tagfalsev26.34.0-rc.2tagtruev26.33.2tag_index.mdv26.34.0tagv26.34.0cutv26.34.1tagv26.35.0-rc.1tagv26.35.0tagv26.36.0tagv26.37.0tag_index.mdv26.38.0-rc.1tagThe arithmetic lines up and explains the divergence.
v26.34.0was cut 14minutes before its own fix merged, so it shipped the graceful default with
SQL-530 intact and went to Cloud on 07-21. The bug bit, and the flag was
turned off on 07-24 while Cloud was still on
v26.34.0.v26.34.1carriedthe fix from 07-23 but went to Self-Managed only, so Cloud never ran a
fixed v26.34 at all and only got the fix when
v26.35.0rolled out on 07-29.The 07-31 re-enable sits two days after that rollout, which is what the
maintainer's "you know when we re-enabled it" points at: the first Cloud
release carrying the fix is v26.35.0, not v26.34.1.
The release notes already draw exactly this split, which is the strongest
evidence available and does not depend on inferring anything.
v26.34.0'snotes never mention the feature.
v26.34.1's notes announce "AsynchronousCluster Reconfiguration" under an explicit "Materialize Self-Managed only"
marker and list the single-replica-source deadlock among its bug fixes.
v26.35.0's notes announce the same feature with a Cloud release date.So no single number is accurate for both audiences, and the page now says
both rather than picking one that is wrong for half the readers:
v26.35 on Cloud, v26.34.1 on Self-Managed. The version moves out of
the heading, which can no longer carry one number, into a sentence in the
body. Nothing linked the old heading's generated anchor, so nothing dangles.
Two honest caveats for a reviewer with LaunchDarkly access. First, the
maintainer did not name the flag, and this repo cannot identify it: the two
flags that produce the graceful default,
enable_cluster_controllerandenable_background_alter_cluster, are both listed inKNOWN_MISSING_FROM_LD(lines 191-438), the parameters that "exist in Materialize but have no
LaunchDarkly flag", and
enable_cluster_controllerappears there twice inv26.37.0, which suggests hand-editing around it. That list is self-describedas drifting and pruned lazily, so its absence is evidence rather than proof.
Either way the conclusion holds, because it rests on the tags and the release
notes rather than on the flag. Second,
v26.34.0is still a version aSelf-Managed operator can be running, and on it a bare resize of a cluster
hosting a single-replica source will stall and roll back at its 24-hour
deadline. The page does not currently warn about that. Worth deciding whether
it should, though a defect in a superseded patch release is arguably not a
docs-worthy version boundary.
Update 2026-09-04: merged with
main, and the claims re-validatedmainmoved 315 commits while this PR sat.origin/mainis merged in. Oneconflict, in
doc/user/content/sql/alter-cluster.md, over the legacy sectionheading: upstream deleted the bare
{{< private-preview />}}badge under it,and this branch deleted that same badge and retitled the heading to "Resizing
in v26.33 and earlier". Both sides removed the badge, so the resolution keeps
this branch's version and nothing is duplicated.
Two upstream changes overtake parts of the original diff. Both are taken as-is
rather than re-asserted:
enable_zero_downtime_cluster_reconfigurationfeatureflag, so
WITH (WAIT ...)is now accepted unconditionally, and the samecommit removed every private-preview label from
alter-cluster.mdand fromthe
WITHoptions table inalter_cluster.yml. The paragraph this PR addedsaying the
WAIToptions are "additionally gated behind" that flag onself-managed deployments no longer matches the code, so it is dropped. Open
question 2 above is moot as a result: there is no badge left to decide about,
and the flag it discussed is gone. The verification note above about "the
labeled badge stays" is superseded for the same reason.
WAIT FORroll back on timeout rather than committingregardless of hydration status. Upstream rewrote that bullet on the page and
in the YAML options table, and the merge takes upstream's wording rather than
this branch's older "commits when it expires ... prefer
WAIT UNTIL READY"text.
The self-managed troubleshooting note keeps its feature-flag sentence, because
that warning is scoped to v26.37 and earlier, where the gate did apply. It now
reads "On those versions the option is also gated behind ...", so the scope
cannot be misread as current.
v26.38 has shipped, tagged
v26.38.0on 2026-08-19, and its release notescarry "Self-Managed: Graceful resizing of system clusters". The caveat in Open
question 1 that v26.38.0 final was not out yet no longer applies. The version
numbers in the diff are unchanged and still correct against the tags. The one
wording change is "System clusters resize gracefully starting in v26.38",
which read as a promise about an unreleased version and is now "in v26.38 and
later".
The three code claims were re-checked against current
mainand all stillhold:
src/adapter/src/coord/sequencer/inner/cluster.rsis gated only on
ENABLE_BACKGROUND_ALTER_CLUSTER, with no reference to thewait strategy, and that dyncfg still defaults
true(
src/adapter-types/src/dyncfgs.rs).controller_ownsis still hardcodedtruein the same file, so theforeground wait shim and the direct create/drop branches remain unreachable.
src/adapter/src/coord/cluster_controller.rsis still
.filter(|c| c.is_managed()), with nois_user()conjunct.DEFAULT_CLUSTER_RECONFIGURATION_TIMEOUTis still 24 hours, so the deadlinefigure on the page is unchanged.
The
SIZEdowntime warning inalter_cluster.ymlwas not fixed upstream,so that hunk is still needed and is retained.
Re-verified after the merge: the YAML still parses, every in-page anchor still
resolves including the links rendered from the YAML data file, and both
#resizing-in-v2633-and-earlierand#system-clustersexist. The headingsthis PR renamed have no inbound links from elsewhere in
doc/user/. The onlyinbound links to the page target
#monitoring-a-resize,#speed-up-hydration-by-autoscaling-to-a-larger-sizeand#system-clusters,all of which resolve.
Generated by Claude Code