Wiki.js 3: What Changed and How to Migrate from 2.x
If you run Wiki.js 2.x, there's one thing to know before you touch anything: Wiki.js 3 can't be installed over your existing wiki. The first stable 3.0 release landed on November 1, 2026, and the project calls it "a complete rewrite of both the backend and frontend." The upgrade guide is blunt: "an in-place upgrade is not possible."
So changing the version number isn't the way in. You stand up a new instance, export from the old one, and import. That's more work than a normal update, but it also makes the move fairly safe, since your 2.x wiki keeps running the whole time.
Here's what actually changed, how the migration works, and what breaks along the way.
What's New in Wiki.js 3
The release post has the full tour. These are the parts most teams will care about:
- New editors and live collaboration. Markdown and AsciiDoc now use the Monaco engine, a new Visual editor stores content as Markdown, and most editors support editing together in real time.
- New page types. Drawing (Excalidraw), Feedback Boards, Blog and Live Notes.
- Approvals and lifecycle rules. Groups can submit edits for another group to review, and rules can flag stale pages automatically.
- Multi-site. One instance can serve several wikis, with users and groups shared across them and content kept separate.
- A built-in MCP server. This one gets its own section below.
What You Need to Run It
The requirements are stricter than 2.x, and the database is the one that catches people out:
| Requirement | Wiki.js 3 |
|---|---|
| Database | PostgreSQL 17 or 18 only, with the ltree and pg_trgm extensions |
| CPU | 1 core works, 2 or more recommended |
| RAM | At least 1 GB on Linux |
| Storage | At least 1 GB, plus your uploads |
| Docker image | ghcr.io/requarks/wiki:3, about 850 MB |
If your 2.x wiki sits on MySQL, MariaDB, SQLite or an older PostgreSQL, that's fine. The export package doesn't care, because you're importing into a fresh database anyway.
One more rule from the docs: never use the latest image tag. Stick with 3, or pin an exact version.
Should You Move Now?
My honest take: try it now, and move production when you've tested your own content. Wiki.js 3 is days old. Versions 3.0.2 and 3.1.0 have already shipped security fixes, including one that revokes user sessions on deactivation and group changes, and another for HTML sanitizing on the client. That's a good sign for how the project handles reports, but it also means you should start on 3.1.0 or newer, not 3.0.x.
You don't have to rush off 2.x either. It got a release as recently as September 2026 (2.5.315), though I couldn't find a published end-of-support date, so keep an eye on it.
How the Migration Works
1. Update 2.x, then export. Bring your old wiki to the latest 2.x version. Then go to Administration Area > Utilities, open Export for Wiki.js 3.x, leave every box checked, click Create Package and download the .wkbackup file.
2. Install a new 3.x instance. This is a separate service with its own database and its own hostname for now. Log in with the root admin account.
3. Import. Go to Administration Area > Utilities > Import from Wiki.js 2.x, select your file and click Start Import. Watch the progress for errors.
The import is safe to repeat. Existing items are skipped unless you tick Overwrite on conflict, so you can do a trial run now and a final import on cutover day.
4. Redo what doesn't come across. Module settings (storage, authentication, comments, analytics), security settings, the logo and the hostname are all left out on purpose. If your staff log in through SSO, set that up again before you invite them over.
5. Fix your content. Most pages come through fine, but some syntax changed:
| Content | What to change in 3.x |
|---|---|
| Relative links | They now resolve from the parent folder. On /foo/bar, [ABC](xyz) goes to /foo/xyz, not /foo/bar/xyz |
| Diagrams | Wrap them in content blocks, such as block-diagram for Mermaid and block-plantuml |
| Draw.io | Export as XML from 2.x and paste into a ::block-drawio block |
| Tabsets | {.tabset} shows as plain text. Rewrite with :::block-tabs |
| Inline math | Needs dollar signs and backticks together |
Relative links are the sneaky one, because the page still looks fine and the link only breaks when somebody clicks it. Check your busiest pages first.
6. Cut over. Do the final import, point your domain at the new instance, and keep the 2.x service around for a while in case something turns up missing.
The MCP Server: Your Wiki as Agent Memory
This is the feature I'd try first. Wiki.js 3 ships an MCP server at /_mcp, so an AI assistant can search, read and, if you allow it, edit your documentation. It's off by default, and the MCP docs list what has to be on:
- Turn it on under Administration Area > MCP. API access and personal access tokens must also be enabled.
- Give the relevant group the
use:mcppermission. - Create a token under Profile > Personal Access Tokens > Connect an AI Assistant, with the AI Assistants (MCP) scope.
Then connect your client. With Claude Code, for example:
claude mcp add --transport http wiki https://wiki.example.com/_mcp \
--header "Authorization: Bearer YOUR-TOKEN"
The safety model is well thought out. The assistant acts as the token's owner and can only do what that person can do. Every write needs a reason, shows up in page history and carries an AI badge. A write gets refused if the page changed since the assistant read it, or if someone has it open in the editor. There are no admin tools at all, and move, delete and file access are off until an admin enables them.
Start with a read-only token. Write access needs Read & Write on both the category and the MCP scope, and scopes can't be changed later, so you'll create a new token when you're ready. Giving an agent search over your docs is useful on day one. There's also suggest_edit, which sends changes to human reviewers, and that's the sensible next step.
Running It on Elestio
Wiki.js on Elestio starts at $11/month for the VM, with automated backups, updates and SSL included.
Deploy a new service for 3.x rather than changing the version on your 2.x service. Pick 3.x from the version list if it's offered, and if not, ask support. Then confirm the database before importing:
docker compose exec -T postgres psql -U postgres -c "SELECT version();"
Replace postgres and the username with what your docker-compose.yml uses. If the database is below 17, 3.x won't run on it. You can edit the stack from Update config in the dashboard, or ask AI DevOps to do it. Attach your custom domain when you cut over.
Troubleshooting
create_page and update_page are missing for your assistant. Those tools need the Puppeteer extension. It ships with the container image, so check that it's enabled. Without it, assistants can only use suggest_edit.
A page written by an assistant is blank. Rendering happens in the background and can take a few seconds. The page isn't searchable until then either.
The assistant gets HTTP 429. That's the MCP rate limit. Clients should wait for the Retry-After delay, and admins can adjust Burst and Refill Rate.
Diagrams or tabs show up as raw text. That's the old syntax from step 5. Wrap diagrams in content blocks and rewrite tabs.
Staff can't sign in after the import. Authentication settings aren't imported. Set your provider up again on the new instance.
Thanks for reading ❤️ See you in the next one 👋