7. Lessons Learned
Do not restore a V14 backup directly to a V16 bench for production. It is technically possible but the risk of a mid-migration patch failure leaving the database in an irrecoverable partial state is too high. The two-step approach gives you a clean, tested V15 state to fall back to.
The V15 staging bench is not just a stepping stone — it is a full test environment. Invest the same rigour in V15 UAT as V16 UAT. Issues caught in V15 are much simpler to fix than the same issue discovered during V16 migration.
Treat each version hop as its own project with its own go/no-go gate. Do not compress the two hops into one sprint.
Vue 2 to Vue 3 is always the longest task and is easily underestimated. Audit all custom Vue components on Day 1 and start the rewrite immediately — do not wait for staging to be ready.
Keep V14, V15, and V16 custom app branches separate and clearly named. Merging incompatible changes between branches caused the most time-consuming confusion during our migration.
On production cutover day, take the fresh backup from V14, run it through hop 1 (V15) completely, then hop 2 (V16). Do not try to combine or shortcut the hops even if timing is tight.
Document every command run in production in a shared real-time log. This is essential for debugging if something goes wrong and for writing the post-migration retrospective.
Run bench doctor after each hop and after go-live. It catches worker, Redis, and configuration issues that are easy to miss in smoke testing.
End of Document — Frappe Framework V14 to V16 Migration Guide