The Studio

Drafts, publishing and discarding

What actually happens in the database when an editor types, publishes or discards — and why a draft is a row rather than a status.

Every document may exist twice: as <id> and as drafts.<id>.

  • Typing creates the draft row if it does not exist — copying the published document first — and patches it.
  • Publishing replaces the published document with the draft and deletes the draft, in one transaction.
  • Discarding deletes the draft and leaves the published document untouched.
  • Unpublishing creates a draft from the published document and then deletes the published row, so the content survives but the URL stops resolving.

Why a row and not a status field

Because both versions have to exist at once: the site keeps serving what is published while an editor works on what is next. A status column cannot represent that without keeping two copies anyway, and publishing then becomes a field update that must be undone if anything downstream fails.

As rows, publishing is one transaction with a clean failure mode, and the constraints that matter — a strong reference to something unpublished, a slug already taken — are checked at exactly the moment they become real.

What an editor sees

The Studio shows a document with unpublished changes as such, and the timeline shows both. This deployment ships a post that is published and has a draft on top of it, precisely so the workflow is visible without anybody having to create one.

What the public site sees

Nothing of the draft. The site reads with no session, which means the published perspective, which means the draft row is not visible to that database connection at all. A draft-only document is a real 404, not an empty page with a 200 — which matters, because a crawler cannot tell those apart.