Skip to content

Document the storage upgrade - #263

Merged
jphenow merged 11 commits into
mainfrom
jphenow/storage-upgrade
Oct 10, 2026
Merged

jphenow merged 11 commits into
mainfrom
jphenow/storage-upgrade

Conversation

@jphenow

@jphenow jphenow commented Oct 9, 2026

Copy link
Copy Markdown
Member

What this gets us

Sprites created before SBD became the default run their disk on the older storage. Moving across is a one-time, customer-initiated upgrade, and nothing in the docs described it — so every request for it has been a support conversation.

Approach

It's a new Storage Upgrades section in sprite-maintenance.mdx rather than a page of its own. It's the same shape as the OS upgrade already on that page — an older version that has to be moved forward deliberately — and it needs no new docs.json entry for something we expect to delete once the fleet is across.

Every command runs against code that's already shipped:

Step Command
Which storage is this on? sprite exec -- printenv SPRITE_STORAGE_DRIVER
Which of my Sprites need it? sprite list | while read loop
Local copy first sprite file pull -r -p
The upgrade, and the rollback sprite api … /upgrade

Two details are called out because a customer can't discover either and getting either wrong costs a restart:

  • curl -N. The upgrade endpoint streams NDJSON progress and holds the response open for the whole upgrade. Without -N curl buffers all of it, so a multi-minute upgrade prints nothing and reads as a hung command.
  • Record the version first. Afterwards the API's version field reports the version that was moved to, and nothing records the one it came from, so the rollback target is unrecoverable if it wasn't written down.

No version numbers are named. A Sprite whose release line has nothing newer published to it is told to contact support rather than given a build that goes stale in the page.

Checks

Six bash blocks, all bash -n and shellcheck clean. <Info> / <Warning> tags balanced. Components match what the rest of the docs use. Mintlify renders the MDX with no build step, so there's nothing to compile.

Worth a second opinion

  • Section vs. its own page. I chose a section because it's one-time and because it keeps the nav unchanged. If this is going to be linked from outside the docs — a support macro, a changelog post — a page with its own URL is easier to point at.
  • The retirement language. The section says the older storage "will eventually be retired" with no date and no promise of notice. That's the conservative wording; if there's a horizon worth stating, this is the line to change.
  • jq as a dependency. Two commands pipe through it. It's ubiquitous, but it's the only third-party tool the page assumes.

Note, not part of this change

CLAUDE.md in this repo describes an Astro Starlight site with src/content/docs/, pnpm dev and Cypress tests. The repo is Mintlify — root-level .mdx, docs.json, and a package.json that says the pages "need no build". .vale.ini and the Vale workflow both filter on src/content/**, so prose linting currently matches nothing. Left alone here; happy to fix separately.

🤖 Generated with Claude Code

Sprites created before SBD became the default run their disk on the
older storage, and moving across is a one-time, customer-initiated
upgrade. Nothing in the docs described it.

It goes in Sprite Maintenance rather than a page of its own: it is the
same shape as the OS upgrade already documented there — an older
version that has to be moved forward deliberately — and it needs no
new navigation entry for something we expect to delete once the fleet
is across.

Every command works against shipped code: `sprite exec` to tell which
storage a Sprite is on, `sprite file pull -r` for a local copy, and
`sprite api` for the upgrade and the rollback. Two details customers
cannot discover for themselves are called out, because getting either
wrong costs a restart:

  - `curl -N`, without which the upgrade endpoint's progress stream
    buffers and a multi-minute upgrade looks like a hung command.

  - Recording the current version first. Afterwards the version field
    reports the version that was moved to, and nothing records the one
    it came from, so the rollback target is unrecoverable if it was
    not written down.

No version numbers are named. A Sprite whose release line has nothing
newer published to it is told to contact support rather than given a
build that will go stale in the page.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
@mintlify

mintlify Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
fly-io 🟢 Ready View Preview Oct 10, 2026, 2:53 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

Neither promise was ours to make. "Contact support and we'll do the
copy with you, including verifying it file by file" describes a service
we do not offer, and "bringing your checkpoint history across is
possible on request" describes a mechanism that does not exist.

The copy is two commands, so show them. `sprite file pull -r` and
`push -r` move the paths you name; `sprite-env services list` is how
you find what else needs setting up again, since services, environment
variables and configuration do not copy.

The checkpoint-history paragraph now points at the new-Sprite route,
which genuinely preserves history: the old Sprite is untouched, so its
checkpoints stay restorable for as long as it is kept. That replaces an
offer with something the reader can act on.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
Two things the page should not have said.

It named support four times. People reach out when they need to; a
doc that routes them there is adding a step, and in two of the four
places it was describing work we do not do.

Worse, it told readers that moving to a new Sprite preserves their
checkpoint history. A new Sprite is a fresh Sprite — it has no
checkpoints, and nothing carries them over. What is true is only that
an untouched old Sprite still has its own, which is not a migration
route and should not be dressed as one. The claim is gone; the warning
now says plainly that pre-upgrade checkpoints cannot be restored and
that anything needed from one has to be copied out first.

The three remaining cases now state the situation and stop: an empty
release lane needs an explicit version, a failed upgrade means stop
writing to the Sprite, and a repeat upgrade after a rollback does not
copy across what was written in between.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
"Don't repeat the upgrade after going back" was the whole of it once
the support line came out, which leaves someone who has rolled back
with no route to the newer storage at all.

Moving to a new Sprite is that route, and it is already the next
section: a new Sprite converts nothing, so the reused-copy problem
cannot arise. The warning now says why the second attempt does not
work and where to go instead.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
Everywhere else the page can tell someone what to do themselves. This
case cannot: a Sprite upgraded, rolled back, written to, then upgraded
again reuses the copy the first upgrade made, and the work from in
between is only reachable by renaming the stale volume aside on the
machine. That is internal, so the page should say so rather than leave
someone staring at missing files.

It states what is true and stops there. Nothing has been deleted, and
the in-between work is still on the older storage; it does not promise
a recovery or a timeline.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
Moving to a new Sprite is the option with less to go wrong, so it goes
first. No disk conversion runs, the existing Sprite is untouched, its
checkpoints stay restorable, and the rollback is to carry on using the
Sprite you already have. What it costs is a new name and URL and
setting services and configuration up again.

Upgrading in place is now second and labelled for what it is: less
work, and the one with something to go wrong. Everything specific to
it — the checkpoint warning, the local copy, writing down the version,
the upgrade itself and going back — sits under it rather than reading
as the only route.

Checking whether a Sprite needs upgrading stays at the top, since it
applies either way, and now ends by naming the two routes.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
The new-Sprite route loses more than files and services. Connectors
are organization-scoped, so they do not need recreating — but their
access policy picks Sprites by name prefix and by label and is
deny-by-default, so a Sprite with a new name and no labels matches
nothing and cannot reach any connector.

That makes labels the load-bearing part rather than an afterthought,
and the fix is usually one flag on create, so the warning gives it.
Name-prefix policies need the new name to match the prefix, or the
policy widened, which is noted rather than solved.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr

@kcmartin kcmartin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left several copy edit suggestions, hope this helps!

Comment thread sprite-maintenance.mdx Outdated
Comment thread sprite-maintenance.mdx Outdated
Comment thread sprite-maintenance.mdx Outdated
Comment thread sprite-maintenance.mdx Outdated
Comment thread sprite-maintenance.mdx Outdated
Comment thread sprite-maintenance.mdx Outdated
Comment thread sprite-maintenance.mdx Outdated
Comment thread sprite-maintenance.mdx Outdated
Comment thread sprite-maintenance.mdx Outdated
Comment thread sprite-maintenance.mdx Outdated
All 21 suggestions from the review, taken as written.

The substantive ones: the intro now says plainly that existing Sprites
are not upgraded automatically and the upgrade has to be requested;
the two routes are introduced as a recommendation rather than a
characterisation of risk; "Going back" is "Rolling back"; and the
detection step leads with what the reader is doing rather than with
the Sprite being asked.

The rest tighten wording throughout — second person, shorter clauses,
and the benefit bullets stated as outcomes rather than mechanisms.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
Two mechanical slips rather than wording choices, so they are separate
from the copy edits and can be dropped on their own.

The connectors warning lost the period that closes its bold lead-in,
which every other callout on the page has. And `sprite-env services
create` lost its backticks, leaving a command rendered as prose.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
@jphenow

jphenow commented Oct 10, 2026

Copy link
Copy Markdown
Member Author

Thank you @kcmartin ! updated!

@kcmartin kcmartin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

The old snippet piped sprite list into while read, so the loop's stdin was the
list itself and sprite exec attached and drained it: the first Sprite consumed
every remaining name and only one line of output appeared. A for loop keeps
stdin on the terminal, so exec attaches nothing and no redirect is needed.

Run the remote side as sh -c 'echo $SPRITE_STORAGE_DRIVER' rather than printenv,
which exits 1 when the variable is unset and made sprite exec print "Error: exit
status 1" for exactly the Sprites being looked for.

Print the Sprites that need the upgrade instead of every Sprite's driver.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
printenv exits 1 when the variable is unset, so the first command in the section
greeted a JuiceFS Sprite — the reader it is written for — with "Error: exit
status 1" and no value. Match the organization-wide loop.

Claude-Session: https://claude.ai/code/session_01JvqUYVtkXDQ5m4n5vaH9sr
@jphenow
jphenow merged commit 6aa6443 into main Oct 10, 2026
1 check passed
@jphenow
jphenow deleted the jphenow/storage-upgrade branch October 10, 2026 03:00

This branch was successfully deployed

1 active deployment
staging — 3363495f Deployed Oct 10, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants