Sulu Version Restore Buys You a Draft, Not an Instant Rollback
Sulu's restore button doesn't touch the live site — it rebuilds your draft from an old version. Here's the two-step rollback, its limits, and how to drill it before an incident.
07 Jan 2026, 20:39 UTC

Friday, 16:55. Someone publishes a homepage edit that wipes out the hero section, and the broken version is now what every visitor sees. The instinct is to hit whatever button looks like "undo" and be done. In Sulu, that button exists — but it does something more careful than most editors expect: restoring a version rebuilds the draft, and the live site does not change until someone publishes again. That two-step shape is the whole point of Sulu's versioning model, and understanding it changes how you assign permissions, how you drill rollbacks, and where you need to plan ahead.
Draft and published are separate states, not two copies of one page
Every content document in Sulu — a page, an article, a snippet — has two distinct states per locale (per language): a draft and a published version. Clicking Save writes to the draft only. The website renders the published state, so an editor can experiment all afternoon without a single visitor noticing. Clicking Publish snapshots the current draft as a new version in the document's history.
That snapshot then becomes fixed history. You cannot accidentally edit a published version in place; you can only create a new draft on top of it. This assumes Sulu 2.x — the admin layout and panel labels shift slightly between minor versions, so verify names against the docs for the release you run.
What "restore version" really does
In the Sulu admin, the Versions panel (in the right-hand sidebar while editing content) lists the published versions of the document with timestamps and authors. Restoring one does not revert the live site. It copies the chosen version's content into the current draft.
Two consequences follow. First, rollback is never accidental: a stray click in the version history cannot change what the public sees. Second, rollback requires the right to publish — Sulu's permission model treats publishing as its own permission per content type, so an editor who can restore a version but not publish is stuck with a corrected draft until someone with publish rights approves it. That is either a safety feature or a bottleneck, depending on how you staff your team.
The same mechanic gives you a free "discard my draft" move: if an editor made a mess but never published, restoring the most recent published version into the draft effectively throws the unwanted edits away.
Worked example: rolling back a broken homepage publish
Say the bad hero change above was published at 16:55, and the last good version went out at 14:10 the same day. The recovery path in Sulu 2.x:
- Open Content → Pages in the admin and navigate to the homepage.
- Open the Versions panel in the sidebar and find the 14:10 entry. If you are unsure which version is the good one, restore candidates one at a time and inspect the form — the live site stays untouched throughout.
- Click Restore on that version. Expected check: the edit form now shows the old content, and the live homepage still shows the broken version. That is correct, not a bug.
- Use the preview pane to confirm the restored content renders properly.
- Click Publish. Expected check: the live homepage shows the restored content, and a new version entry appears at the top of the Versions list — the rollback itself is now part of the history.
The decision you actually make first is diagnostic:
| Situation | Live site affected? | Fastest fix |
|---|---|---|
| Bad edit saved as draft only | No | Restore the latest published version into the draft, or just re-edit |
| Bad change published | Yes | Restore last good version → preview → publish |
| Bad change published, several publishes since | Yes | Identify the good version by timestamp, restore, review in preview before publishing |
Trade-offs worth planning for
Storage grows with every publish
Each publish writes a full version snapshot into Sulu's content repository (Sulu stores documents via PHPCR, a Java Content Repository-style API, typically backed by Jackalope), so a site that publishes heavily — especially one with automated imports — accumulates history without bound. Sulu does not prune old versions for you. Decide on a retention policy, and check what cleanup options your specific version offers rather than assuming a command exists. Running bin/adminconsole list from the project root (with the database credentials your console context uses) shows which maintenance commands your installation actually ships.
Rollback is per locale
Versions are tracked per language. Restoring the English homepage does nothing to the German one, which is exactly what you want for a mistranslation — but a site-wide rollback across five locales is five separate restore-and-publish operations. Plan who does them and in what order.
The built-in workflow is two states
Sulu's core editorial model is draft → published. If your organization needs an explicit review or approval stage between them, that is an extension point, not a configuration toggle: teams wire in Symfony's Workflow component or a bundle, and hook custom logic through Symfony's event system. One caution from that path: validation that runs synchronously on publish or transition adds directly to admin response time, so push heavy checks to a queue.
Before you need this: a five-minute drill
Do not let the first version restore happen during an incident. On a staging copy: publish a page, make and publish a deliberately broken edit, restore the previous version, and confirm the live page only changes at the publish step. Along the way, verify three things — that your editors can see the Versions panel, that whoever handles incidents holds publish permission, and that your backups include the content repository where version history lives. If any of those three fails in the drill, you have found the gap while it is still cheap to fix.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.