Deploying Frappe With Confidence

DevOps — Ali Raza

Deploying Frappe With Confidence

How Docker, Linux and deployment discipline improve Frappe reliability.

The first time I broke a production ERPNext site, it was a healthcare client and the cause was embarrassingly small: I ran bench update on the live server during working hours, a patch touched the Patient Appointment DocType, and the schema migration locked a table while the front desk was booking appointments. Nobody lost data, but for eleven minutes nobody could work either. Everything I now do around Frappe deployments traces back to moments like that one.

The core problem is that a Frappe deployment is never just "new code". It is code plus database migrations plus rebuilt assets plus background workers plus the scheduler, and they all have to move together. If you ship code that renames a field but the migration has not run, every Server Script and Query Report touching that field starts throwing errors. If you migrate but forget to restart the workers, your queues keep executing stale Python against a new schema. Treating those as one atomic unit is the whole discipline.

Docker is what made that atomicity practical for me. I build a custom image from frappe_docker with our apps baked in at a pinned commit, tag it with the git SHA, and that image is what goes to staging and later to production, unchanged. No more "it worked on staging" mysteries caused by a stray git pull on the server or a different Node version rebuilding assets slightly differently. The bench directory on a hand-managed VM accumulates drift the way a desk accumulates paper; a versioned image cannot.

The deployment sequence itself is boring, and boring is the point. Enable maintenance mode, take a backup with bench --site all backup --with-files, swap the containers to the new image, run bench --site all migrate, restart workers, disable maintenance mode. On a municipal government project we wrapped this in a single script precisely so that a 2 a.m. hotfix follows the identical path as a planned release. The moment deployments have a "quick way" and a "proper way", someone will use the quick way on a Friday.

Backups deserve their own paranoia. A backup you have never restored is a rumor, not a backup. Once a month I restore the latest dump into a scratch site with bench --site test.localhost restore and actually log in, open a few DocTypes, run a Query Report. That drill is also where you discover that site_config.json holds the encryption_key, and that without it every stored password and OAuth credential in the restored database is unreadable. Back up site config alongside the database or your disaster recovery plan has a hole in the middle.

On the Linux side, most "Frappe is unreliable" complaints I have debugged were really host problems. MariaDB with default settings will fall over under a real workload; set innodb_buffer_pool_size to something proportional to RAM and enforce utf8mb4 or emoji in a customer name will one day fail an insert. Watch Redis memory, because the cache and queue databases share a host and a hungry queue can evict sessions. And check that vm.overcommit_memory is set the way Redis asks, because the warning it prints at startup is not decorative.

Customizations are the last place discipline pays off. Anything created through the UI on production — a workflow with new states, a custom field, a Notification — is invisible to your next deployment and will silently diverge between environments. Everything lives in a custom app: fields as fixtures, workflows exported, patches written in patches.txt for data changes. On an HR portal project we had a rule that if it is not in the app repo, it does not exist, and that rule ended an entire category of "works on prod, broken on staging" tickets.

None of this is glamorous. But the Frappe Framework gives you sharp, capable tools — bench, migrations, the scheduler, hooks — and reliability comes from using them the same way every single time. The clients running their hospitals, city services, and HR operations on ERPNext do not care how clever the deployment is. They care that Monday morning, the site is up, the data is intact, and the appointment queue moves. Confidence is not a feeling; it is a script you have rehearsed.