Every time we inherit an ERPNext system in trouble, the same pattern emerges: early customizations done without discipline that compound into an un-upgradable swamp. Don't let that be you.
Rule 1 — Configure before you customize
Nine times out of ten, what the user calls a customization is actually a configuration that already exists. Exhaust configuration before writing any code.
Rule 2 — Customize through the UI where possible
Custom fields, custom DocTypes, client scripts, server scripts and workflows can all be done through the Frappe UI. These are upgrade-safe. Python overrides are not.
Rule 3 — Always use a custom app
Never edit core ERPNext code. Create a dedicated custom app, keep customizations there, and version it in git.
Rule 4 — Don't fork standard DocTypes
Extend them via custom fields. Forking a standard DocType means inheriting every future upstream change manually.
Rule 5 — Document every customization
A one-line comment in code, a row in a shared tracker, and a reason. Future-you (or your successor) will thank you.
Rule 6 — Plan for upgrades from day one
Every customization should have a documented upgrade strategy. If you can't explain how it will survive the next major version, don't build it.