Guide
A Storyblok deployment workflow that does not break production
Preview, staging, production — how content actually moves between them, what deployments copy, and what to do when the feature is not on your plan.
Last updated August 2026
Code has environments. Content usually does not, and that asymmetry is where accidents come from: an editor publishes to check a layout, and it is live. A deployment workflow fixes that by giving content the same forward-only path your code already has.
The shape of the workflow
Editors work here Frozen Frozen
┌───────────┐ ┌─────────┐ ┌────────────┐
│ Preview │ ──────▶ │ Staging │ ────▶ │ Production │
└───────────┘ deploy └─────────┘ deploy└────────────┘Only Preview accepts edits. Everything downstream is read-only and changes only when you deploy into it. That single constraint is what removes merge conflicts from content entirely — promotion is always a fast-forward.
Step 1 — decide where each stage pulls from
A stage names its upstream with source_id. Two shapes are common, and both are valid:
| Shape | Lineage | Use when |
|---|---|---|
| Chain | Preview → Staging → Production | You want QA to sign off on exactly what ships |
| Hub | Preview → Staging, Preview → Production | Stages are independent previews for different audiences |
The chain is the safer default: production receives content that has already sat in staging, rather than whatever is currently in Preview.
Step 2 — deploy into a stage
POST /v1/spaces/:space_id/deployments
{ "branch_id": 12345, "release_uuids": [] }branch_id is the destination, not the source. Storyblok reads that stage’s source_id and copies content forward from there. You deploy a stage; you do not name a direction.Leave release_uuids empty and the whole source stage moves. Supply specific releases and only those do, which is how you ship one campaign to production while unrelated work stays in staging.
What actually moves
- Published content only. Drafts stay in Preview.
- Story ids are reassigned in the target stage;
uuidstays constant. - References are rewritten to the target stage’s ids.
- Nothing flows backwards. A frozen stage cannot be edited and pushed upstream.
What does not move
- Component schemas. These appear to be space-wide, so a breaking schema change reaches frozen production content immediately, with no deployment involved. Content is staged; structure is not.
- Assets. Also space-wide, with stable URLs across stages.
Step 3 — point each site at its stage
Give every environment a delivery token bound to its stage. The frontend holds that token permanently and never names a branch, so a deployment changes what the site sees without any redeploy or config change:
| Environment | Token | Serves |
|---|---|---|
| Local / editor preview | preview token | Draft and published |
| Staging site | staging token | Whatever was last deployed to staging |
| Live site | production token | Whatever was last deployed to production |
Rollback is the gap
Branch deployments are forward-only. There is no undo: if something wrong reaches production, recovery means fixing it in Preview and deploying again, with the bad content live in the meantime.
That is a consequence of how deployments store content — each stage holds its own copies, and deploying overwrites them. Systems that keep immutable content versions and move pointers instead can offer instant rollback, because the previous state was never destroyed.
If the feature is not on your plan
The /branches and /deployments endpoints require the Pipelines app. /stories and /api_keys do not, and that is enough to build the same workflow outside Storyblok.
Exacta does exactly that: editors keep working in your Storyblok space, Exacta mirrors its published content, and branches, promotion and per-branch tokens live on our side. Your frontend swaps api.storyblok.com for api.exacta.im and keeps the identical response shape.
Common questions
- How do I deploy content from preview to staging in Storyblok?
- POST to /v1/spaces/:space_id/deployments with the target stage as branch_id. Storyblok reads that stage’s source_id to decide where the content comes from, so you deploy the destination rather than naming a direction.
- Does a Storyblok deployment move unpublished drafts?
- No. Deployments move published content only. Drafts stay in the Preview stage until they are published.
- Can I deploy only some content?
- Yes. Pass release_uuids in the deployment payload and only those releases move, leaving other work in the source stage.
- Can I roll back a Storyblok deployment?
- No. Deployments are forward-only. Recovery means correcting content in Preview and deploying again.
- Do component schema changes need a deployment?
- No, and that is the risk. Components are space-wide, so a schema change affects every stage immediately including frozen production content.