Infrastructure
Rewriting an invoicing app means planning the exit from the old database
Mavri's move to a Go server and SQLite required a one-time converter for earlier data. What migrated, what did not, and why upgrade instructions must say so plainly.
By Raktim Ranjit · Published · 5 min read
A rewrite is often described as a new interface and a cleaner codebase. For an invoicing app, the hard question is what happens to the records people already depend on. If an upgrade changes the database format, a feature list is incomplete until the migration path and its limits are clear.
The earlier app and the new one are different systems
Mavri 2 moved from an earlier application and database layout to a Go server, SQLite and a React interface in one container. The new deployment is simpler to run, but an operator cannot assume that an old data directory is interchangeable with a new one. Different schemas and storage locations require an explicit conversion step.
The mavri-legacy converter reads a database from an earlier Mavri version and copies invoices, quotes, customers and settings into a new, empty database. It leaves the old file untouched. That is a safer starting point than an in-place mutation because the source remains available if the operator needs to inspect or retry the migration.
Say what does not move
Accounts and store connections are not copied. That is material information, not a footnote: operators should expect to recreate access and reconnect integrations after the data conversion. If a service makes an integration look migrated when its credentials were intentionally excluded, the first failed webhook becomes the release note.
A migration guide should answer four questions before anyone runs a command: which versions are supported, which records are copied, which secrets or external connections must be re-entered, and how to verify the result. Mavri's published instructions point people to the current repository for the exact command and version-specific steps so those details can stay aligned with the release.
Why keep the original database?
A successful process exit only says the converter reached its end. It does not establish that every record is present or that the new app can use it. Keeping the old file intact gives the operator an independent reference for spot checks and a recovery path if the new installation needs to be rebuilt.
Before relying on the new install, check representative invoices and quotes, customer records, settings, totals and document statuses. Then make a fresh backup from the new version and test that it restores. The same habit applies to any business database migration: preserve the source, inspect the destination and test the operational path after conversion.
Migration is also product design
People experience a schema change as an upgrade screen, a command or a support conversation. They do not care that the old database was inconvenient for the new architecture if their records are missing. That makes migration a user-facing feature with its own success criteria: clear prerequisites, a preserved source, an honest list of exclusions and a way to verify completion.
The trade is straightforward. Mavri's newer deployment is built around one SQLite data file and one container, while older installations need a one-time conversion and some setup afterward. We should keep that trade visible in the migration documentation and in the release itself.
What you are migrating to is described in why Mavri serves the web app and API from one container, and document snapshots explain why converted invoices keep their original details. The full write-up of the product is in the Mavri case study; the Mavri website has the install guide and docs.
References
Author
Raktim Ranjit is a software engineer and the founder of NodeDR Infotech. He builds and maintains the software described here.