# Custom ERP development for businesses that ERPNext and Odoo don't fit

Canonical: https://erpfly.com/custom-erp-development/
Last updated: September 5, 2026

Some companies have tried ERPNext, tried Odoo, and spent more time switching features off than using them. If the core of your business is a process no ERP vendor models, custom software can be the right call. erpfly builds it on the Frappe framework, so logins, permissions and the API work before you've written a single rule.

### Deliverables

- **A Frappe app without ERPNext.** Only the DocTypes your business needs. No Item, Warehouse or Sales Invoice screens hanging around unless you ask for them.
- **Logins, roles and record-level access.** Frappe's user system, two-factor login, role permissions and User Permissions, so a centre manager only ever sees their own centre's records.
- **A REST API from the first day.** Every DocType is reachable under /api/resource, and whitelisted methods give tablets, scales and partner systems a narrow, documented way in.
- **Reports, dashboards and print formats.** Report Builder for quick questions, Script Reports for the ones that matter, number cards on a workspace and Jinja print formats for receipts and statements.
- **Background jobs and integrations.** Scheduled jobs through scheduler_events, long tasks on background workers, and webhooks for pushing events to other systems.
- **Room to add ERPNext later.** Because it's a Frappe app, you can install ERPNext on the same bench later and link your DocTypes to its accounting, instead of migrating to a new system.

### Process

1. **Map the documents, not the screens.** We start from the paper and spreadsheets that move through your business. Each one that has a lifecycle usually becomes a DocType.
2. **Generate a thin first version.** A handful of DocTypes, two roles and one report. Your team uses it on real work for a week before anything else gets built.
3. **Grow it one pull request at a time.** Every change arrives as a reviewed pull request with tests and migration patches, so the system never gets ahead of the people using it.
4. **Host it where you like.** Frappe Cloud if you don't want to run servers, or your own infrastructure with bench and Docker. The code is yours either way.

### Most companies don't need a custom ERP

We'll start with the unpopular part. Most businesses that ask for a custom ERP would be better off on ERPNext or Odoo with a few custom modules. Accounting, stock, purchasing and payroll work much the same everywhere, and the standard apps have years of edge cases baked in that a new system will rediscover the hard way.

So before we build anything from scratch, we ask what percentage of your daily work happens inside the parts that are genuinely unusual. If it's a small slice, extend a standard ERP with [ERPNext custom modules](https://erpfly.com/erpnext-custom-module-development/) or [Odoo module development](https://erpfly.com/odoo-module-development/) and keep the rest stock.

### Signs off-the-shelf really doesn't fit

Custom starts to make sense when several of these show up together:

- **Your main transaction isn't a sale or a purchase.** Milk collections, clinical trial visits, container moves, school bus routes. Forcing them into Sales Orders creates fake customers and fake items.
- **You're paying for modules your staff never open.** Half the menu is hidden and still confuses new staff.
- **The pricing logic is the business.** A rate that depends on a lab reading, a route and a date isn't a price list, it's a formula that changes weekly.
- **The users aren't office workers.** People on tablets at a weighbridge need three buttons, not a desk full of menus.

Our write-up on [build vs buy for ERP](https://erpfly.com/blog/build-vs-buy-erp/) goes through this decision in more depth, and the [Odoo vs custom ERP comparison](https://erpfly.com/compare/odoo-vs-custom-erp/) sets the two options side by side.

### What Frappe gives you before the first rule is written

erpfly generates a Frappe app and installs it on a bench without ERPNext. You're not inheriting an ERP. You're inheriting the framework under one, which handles the parts that sink most custom projects:

```text
Comes with the framework       You still decide
--------------------------     ------------------------------
Login, 2FA, password rules     Which roles exist
Role and record permissions    Who sees which centre or route
List, form and report views    What the DocTypes are
REST API and webhooks          Which methods are exposed
Version history on records     Business rules and validation
Print formats, email, files    Rate charts, payment cycles
Background jobs, scheduler     What runs nightly
Data Import from CSV/Excel     How old records are migrated
```

That left column is months of work in a greenfield project, and it's the part people underestimate. Everything erpfly writes goes in the right column.

### Example: milk procurement for a dairy cooperative

Take the cooperative from the prompt. Farmers deliver twice a day to village centres. Each can is weighed and tested for fat and SNF (solids-not-fat), and the price comes from a rate chart that head office revises when feed costs change. Farmers get paid every ten days, less any advances for cattle feed.

ERPNext could technically hold this as Purchase Receipts against thousands of Suppliers, one per farmer. In practice it would be miserable. The centre staff would face a purchase screen built for buyers, and the rate calculation would sit in Server Scripts with no tests and no history.

As a custom Frappe app, it's a Farmer, a Collection Centre, a Rate Chart, a Milk Collection and a Payment Cycle DocType. The controller on this page does the pricing. A whitelisted method gives the tablet one way to record a delivery. User Permissions keep each centre inside its own data. A Script Report shows litres and average fat by route, and a scheduled job builds the ten-day payment run. Feed advances and the ledger go to ERPNext accounting on the same bench, or to whatever the cooperative already uses.

One thing we'd flag early: village centres often have patchy mobile data. Frappe's desk expects a connection, so the tablet side needs a small offline-first app that queues deliveries and posts them to that method when the signal comes back. It's not hard, but it's a real piece of work, and it should be in the plan from week one rather than discovered in week six.

### What it costs, and what goes wrong

We can't give you a sensible number without knowing the scope, and you should be wary of anyone who does. What we can say is where the money goes. The build is the cheap part now. What stays expensive is owning it. Someone has to review changes, keep Frappe up to date, answer "why did this farmer get paid less" and know where the rate logic lives. If that person is one freelancer who moves on, you've got a problem no matter who wrote the code.

The risks we see most often are scope creep (the system slowly grows its own half-built accounting), undocumented rules that lived in one clerk's head, and data migration from years of spreadsheets. None of that is solved by AI. It's solved by a small first version, a named owner inside your company and a developer you can call. Our comparison of [erpfly and hiring an ERP developer](https://erpfly.com/compare/ai-vs-hiring-erp-developer/) spells out which parts still need a person.

### When to choose ERPNext or Odoo instead

- **Your process is mostly standard with a few odd corners.** Customize a standard ERP. It's cheaper to own.
- **You can't name an internal owner for the system.** A custom ERP without an owner decays quickly.
- **You need broad localized accounting and tax on day one.** Standard ERPs carry that work so you don't have to.

If you're torn between the two big open-source options, our [ERPNext vs Odoo comparison](https://erpfly.com/compare/erpnext-vs-odoo/) is a good next read.

### FAQ

### Why build on Frappe instead of starting from a blank Django or Node project?

Because a blank project spends its first months on logins, permissions, list views, audit history, file uploads and an API. Frappe has all of that already, it's open source under the MIT licence, and it's the same framework ERPNext runs on, so hiring help later is realistic.

### Do we have to use ERPNext to use Frappe?

No. Frappe is a framework and ERPNext is one app built on it. A custom ERP from erpfly installs on a bench with just frappe and your own app. You can add ERPNext later if you want its accounting.

### Isn't custom software riskier than buying an ERP?

Yes, and we won't pretend otherwise. You own the maintenance, the upgrades and the knowledge of how it works. What erpfly changes is how quickly you get to a working version you can judge, which makes it much cheaper to find out early that custom was the wrong idea.

### What about accounting and payroll?

Please don't write your own general ledger. For most custom ERPs we either install ERPNext for accounting on the same bench or send journal entries to the accounting system you already use through its API. Payroll is similar, it's regulated and it changes every year.

### Can a mobile app or website use the system?

Yes. Frappe exposes a REST API with token or OAuth authentication. Tablets at the collection centre in the example use a single whitelisted method, so they can record deliveries without being able to read anything else.

### How long before we have something usable?

A first version you can click through usually exists within a day. Something your staff rely on daily takes weeks of real use and changes, and anyone quoting a full custom ERP in days is selling you a demo.

### Sources

- [Frappe Framework repository, Frappe on GitHub](https://github.com/frappe/frappe)
- [REST API, Frappe Framework documentation](https://docs.frappe.io/framework/user/en/api/rest)
- [Users and Permissions, Frappe Framework documentation](https://docs.frappe.io/framework/user/en/basics/users-and-permissions)
- [Hooks, Frappe Framework documentation](https://docs.frappe.io/framework/user/en/python-api/hooks)
- [Webhooks, Frappe Framework documentation](https://docs.frappe.io/framework/user/en/guides/integration/webhooks)