Saaspocalypse
The migration runbook

Migrating off Confluence — phase by phase.

Confluence migrations turn on three specifics: the storage format is XHTML with a forest of `ac:` macros that don't translate cleanly to Markdown, page restrictions inherit through the space hierarchy in non-obvious ways, and content moves to MDX-on-disk + a real search index (Typesense or Postgres tsvector) which finally returns relevant results — the most common complaint about Confluence search.

10-14 weeks end-to-endFixed priceParallel run before cutoverYou own the code

The phases, tuned to Confluence

Each phase below is the Confluence-specific version of our standard playbook. Same shape every engagement, different specifics per SaaS.

  1. Spaces + restriction audit

    1-2 weeks

    We inventory every space, every restricted page, every Marketplace macro in active use, and the URL hierarchy that external systems (engineering docs links, customer-facing help articles) depend on.

    List every space, its admin, and the number of pages + total view count over 90 days
    Identify spaces that haven't been viewed in 90 days — most large Confluences have 30-40% archive candidates
    Audit page restrictions (view + edit) and surface the inheritance model
    Catalogue Marketplace macros in use (Drawio, Scroll, Refined, etc.) — each needs a replacement strategy
    Map URLs to preserve: page IDs, slugs, /wiki/spaces/{KEY}/pages/{ID}/{slug} structure
    You walk away with

    A Space Inventory + restriction map + macro replacement plan + the URL preservation list.

  2. Content model + storage strategy

    1 week

    Pages become MDX files in a Postgres-backed CMS, with version history preserved. The `ac:` storage format gets converted to MDX with our own components replacing the most-used macros (Drawio → mermaid + image, panel → callout component, etc.).

    Design `pages` table (parent_id, space_id, slug, mdx_source, version, restricted_to)
    Design `page_versions` table to preserve history
    Preserve Confluence `page_id` as a column for backwards-compatible URLs
    Map the macro inventory: Drawio → mermaid + S3 image, Scroll → version-controlled MDX branches, Refined → first-class theming, info/note/warning panels → our own callout component
    Plan search: Typesense (or Postgres tsvector) over MDX + metadata + a 1-hour reindex
    You walk away with

    Schema migrations + an MDX component library + a documented macro replacement table.

  3. Extract via Confluence REST API

    2 weeks

    Confluence Cloud's REST API exposes pages, spaces, comments, attachments and permissions. The wrinkle is that the storage format is XHTML with `ac:` macro tags — converting to MDX is the bulk of the engineering work.

    Authenticate via OAuth 2.0 (3LO) or API token with HTTP Basic
    Paginate `/wiki/api/v2/pages` per space (the v2 API is cleaner than v1)
    For each page, GET the storage-format body (XHTML with `ac:` macros)
    Extract attachments, comments, labels and version history per page
    Extract space permissions + page restrictions separately
    Run the XHTML → MDX converter (the hard part — start with the 10 most common macros, iterate)
    You walk away with

    A re-runnable extract pipeline + an MDX corpus + a macro-conversion report showing coverage.

  4. Build + weekly demos

    4-6 weeks

    A Next.js wiki that's faster than Confluence on every dimension that matters: search returns in 80ms, page loads in 200ms, edits commit to git, and restrictions are typed permissions.

    Build the wiki: MDX rendering with the macro-replacement components
    Full-text search via Typesense or Postgres tsvector — relevance ordering, instant suggestions
    Page editor with live MDX preview (authors edit Markdown, designers own CSS)
    Permission model: 4-5 named roles + space-level + page-level restrictions (rows in a typed table)
    Whiteboards / Databases replaced with first-class features or dropped (most teams don't need them)
    You walk away with

    A working wiki on staging with the full content corpus, used by your team for one week as the primary documentation source.

  5. Parallel run + URL preservation

    2 weeks

    Both Confluence and the new wiki live for two weeks. Search points at the new wiki; the old Confluence is editable for a final corrections window. URL redirects from the legacy `/wiki/spaces/{KEY}/pages/{ID}` get tested exhaustively.

    Nightly delta extract: pages updated in Confluence sync into the new wiki
    Set up 301 redirects from every legacy Confluence URL to the new path
    Train authors on the new editor in two 45-minute sessions, recorded
    Disable new-page creation in Confluence (existing edits still allowed)
    Verify the redirect map preserves every external link from engineering docs, runbooks, customer help
    You walk away with

    A reconciliation report on page counts per space + a verified 301 redirect map covering 100% of indexed URLs.

  6. Cutover + Confluence read-only

    1 day + 90-day fallback

    DNS for the wiki subdomain flips to the new product, Confluence goes fully read-only, Marketplace apps get cancelled, the Atlassian Cloud bill drops by the Confluence portion.

    Cut SSO + DNS to the new wiki
    Lock Confluence to read-only (revoke edit permissions space-wide)
    Cancel Marketplace apps (Drawio, Scroll, Refined, etc.) in writing
    Hold a 90-day Confluence read-only window for compliance / regret
    Cancel Confluence Cloud subscription auto-renewal
    You walk away with

    Cutover Runbook + cancelled Marketplace subscriptions + a reduced Atlassian bill the same month.

The Confluence APIs we'd actually hit

Concrete endpoints we use to extract your data during the parallel-run phase. We keep the extract scripts — they're useful at every renewal.

List pages (REST API v2)
GET /wiki/api/v2/pages?limit=250
Paginate every page — v2 is cleaner than v1 and returns more per call
Get page body in storage format
GET /wiki/api/v2/pages/{id}?body-format=storage
Pull the XHTML body with `ac:` macros — the input to the MDX converter
Get page versions
GET /wiki/api/v2/pages/{id}/versions
Preserve version history per page
List spaces
GET /wiki/api/v2/spaces
Enumerate every space + space key (URL component)
Get attachments per page
GET /wiki/api/v2/pages/{id}/attachments
Pull file metadata + download URLs for S3 import
Get comments per page
GET /wiki/api/v2/pages/{id}/footer-comments
Preserve in-line and footer comments (page review history)
Get labels
GET /wiki/api/v2/pages/{id}/labels
Migrate page labels (used for filtering + saved searches)
Get space permissions
GET /wiki/rest/api/space/{spaceKey}/permission
Extract who-can-do-what at the space level for the RBAC mapping

The Confluence-specific gotchas

Things we've learnt the hard way (or that the documentation understates). We'll surface these on the kickoff call so nobody is surprised in week 6.

What stays where it is

Migrations work because they're scoped honestly. Here's what we don't move — by design.

  • ·Whiteboards and Databases — replaced with native equivalents or dropped
  • ·Atlassian Marketplace macros — replaced with first-class MDX components or dropped
  • ·Atlassian Intelligence / AI add-ons — replaced with Claude/GPT against your own corpus
  • ·Confluence Mobile app — the new wiki is mobile-responsive; no native app
  • ·Jira — paired separately (see /jira/migration)
  • ·Trello — separate scoping conversation

Get a Confluence-shaped migration plan.

Tell us your seat count, contract end date, and the integrations you can't lose. We'll come back within a business day with a fixed-price scope and a timeline tuned to your renewal.

Scope a Confluence migration

One business day. NDA + DPA on request.