Skip to content

What Is Frappe? The Framework Behind ERPNext, Explained

Frappe is the full-stack, metadata-driven Python and JavaScript framework that powers ERPNext. Here is what it actually is, how its core pieces fit together, and when it is the right foundation to build on.

By Karani Geoffrey, Founder & CEO, Upeosoft
In short

Frappe is a full-stack, metadata-driven web framework written in Python and JavaScript that powers ERPNext. You define data models as doctypes, and Frappe generates the database schema, REST API, forms, permissions, and admin UI automatically, so you write business logic instead of boilerplate.

Key takeaways
  • Frappe is a batteries-included Python framework, not just an ERP; ERPNext is the flagship app built on top of it.
  • The doctype is the core abstraction: one JSON-plus-Python definition gives you a table, a REST endpoint, a form UI, and permissions.
  • Hooks let your custom app extend core behaviour without forking, which keeps you upgrade-safe.
  • The bench CLI manages sites, apps, migrations, and the background worker and scheduler stack.
  • Frappe ships a full ORM, background jobs via Redis and RQ, a permission engine, and a REST API out of the box.
  • It fits data-heavy business apps far better than a bare framework like Django or Express when you want speed to a working system.

Frappe in one sentence

Frappe is a full-stack, metadata-driven web framework, written in Python on the server and JavaScript on the client, that lets you describe your data models declaratively and get a working application around them almost for free.

Most teams first meet Frappe through ERPNext, the open-source ERP that runs accounting, inventory, manufacturing, and HR for tens of thousands of companies. But ERPNext is just the most famous app built on Frappe. The framework underneath is general purpose, and at Upeosoft we have used it to build systems that look nothing like a traditional ERP: field data collection tools, licensing portals, and industry-specific operations software. Understanding Frappe as a framework, not as ERPNext, is the first step to using it well.

The doctype: Frappe's core abstraction

Everything in Frappe revolves around the doctype. A doctype is a model definition stored as metadata: a list of fields, their types, and their behaviour. When you create a doctype called "Customer," Frappe does a remarkable amount of work for you in one move.

From that single definition you automatically get a database table with the right columns, a REST endpoint at /api/resource/Customer, a list view and a form view in the desk UI, validation, and a permission surface you can configure per role. You did not write a migration, a serializer, a form component, or a controller. That is the metadata-driven idea in practice: the schema is data, and the framework reads that data to build the machinery.

When you need custom logic, each doctype has an optional Python controller class with lifecycle methods such as validate, before_save, on_submit, and on_cancel. That is where your real business rules live, cleanly separated from the plumbing.

  • One doctype yields a table, a REST API, list and form UIs, and permissions.
  • Field types include links to other doctypes, child tables, select, currency, and more.
  • Controller hooks like validate and on_submit hold your business logic.
  • Custom Fields and Customize Form let you extend core doctypes without code.

Apps, sites, and the bench

Frappe organises code into apps and data into sites, and the bench CLI ties them together. An app is a Python package with doctypes, code, and assets; frappe itself is an app, erpnext is an app, and your custom code lives in its own app so it stays separate and upgradeable.

A site is a single tenant with its own database and configuration. One bench can host many sites, and each site installs a chosen set of apps. This separation is what makes multi-tenant hosting and clean upgrades possible.

The bench command is your control panel. You use it to create sites, install apps, run database migrations with "bench migrate," build front-end assets, tail logs, and start the whole development stack. In production, bench also manages the web server, the background workers, and the scheduler through a process manager. Learning bench well is most of learning to operate Frappe.

Hooks: extending without forking

The single most important thing to understand for maintainable Frappe work is the hooks system. Every app has a hooks.py file that lets it register into framework and other-app behaviour without editing that other code.

Want to run a function whenever any Sales Invoice is submitted? You add a doc_events entry in your own app's hooks.py pointing at your function. Want to override a whitelisted method, schedule a nightly job, inject a CSS file, or add a permission query condition? All of it is declared in hooks. Your custom app observes and extends; it never patches core in place.

This is what keeps a Frappe deployment upgrade-safe. At Upeosoft, our rule is simple: core apps like frappe and erpnext are read-only, and everything we build goes into a dedicated custom app wired in through hooks. When ERPNext releases a new version, our code rides along instead of fighting the merge.

Batteries included: API, jobs, and permissions

Frappe ships the parts most teams otherwise assemble by hand. There is a complete REST API for every doctype, plus a whitelisting decorator, frappe.whitelist(), that exposes any Python function as a callable endpoint with authentication and permission checks applied.

Background processing is built in. Frappe uses Redis and RQ to run enqueued jobs and a scheduler for periodic tasks, so long-running work like report generation, emailing, or syncing an external system never blocks a request. You call frappe.enqueue with a function path and it runs on a worker.

The permission system is genuinely deep: role-based permissions per doctype, user permissions that scope records to a value, permission query conditions for row-level rules, and field-level read and write control. For business software, where who-can-see-what is often the hardest requirement, having this built in rather than bolted on is a major advantage.

How Frappe compares to a bare framework

If you have built with Django, Rails, or Express, the trade-off is easy to frame. A bare framework gives you maximum control and a blank canvas; you decide every model, endpoint, and form, and you write all of it. That is the right choice when your product is genuinely novel in shape.

Frappe trades some of that control for enormous leverage on the class of software it targets: record-oriented business systems full of forms, lists, workflows, approvals, and reports. On that terrain, the metadata-driven approach means you reach a working, permissioned, API-backed system in a fraction of the time, because you are configuring behaviour rather than coding infrastructure.

The cost is that you learn Frappe's conventions and work within them. Fighting the framework, for instance by bypassing the ORM or hand-editing core, is where teams get into trouble. Used with the grain, it is one of the fastest ways we know to ship serious business software.

When Frappe is the right foundation

Choose Frappe when your problem looks like structured records that people create, review, approve, and report on, especially if permissions and audit trails matter. Inventory, field operations, licensing, member management, service delivery, and anything adjacent to ERP are natural fits, and you gain even more if you also need ERPNext's accounting or stock modules alongside your custom app.

Look elsewhere when you need a real-time collaborative editor, a high-traffic public site that is mostly cacheable content, or a product where you must own every detail of the request lifecycle and schema. Those are not Frappe's strengths, and forcing them tends to erase its advantages.

At Upeosoft we build on ERPNext and Frappe precisely because so much Kenyan business software is record-oriented and permission-heavy. Starting from a mature, open-source foundation lets us spend our engineering time on the parts that are actually unique to each client, instead of rebuilding auth, APIs, and admin for the hundredth time.

Frequently asked questions

Is Frappe the same as ERPNext?

No. Frappe is the underlying web framework, and ERPNext is a large application built with it. You can build entirely new products on Frappe without installing ERPNext. Think of the relationship the way Ruby on Rails relates to a specific Rails application: one is the toolkit, the other is a product built with it.

What language is Frappe written in?

The backend is Python and runs on a WSGI server, with MariaDB or Postgres for storage and Redis for caching and queues. The client side is JavaScript. Frappe's desk UI is built on its own component library, while newer apps increasingly use Vue 3 for custom front-ends against the same REST API.

How is Frappe different from Django?

Django gives you an ORM and admin, but you still hand-write models, serializers, views, and forms. Frappe is metadata-driven: defining a doctype generates the schema, REST API, list and form views, and permission rules automatically. You trade some low-level control for a very large reduction in boilerplate on data-centric apps.

Is Frappe free and open source?

Yes. Both Frappe and ERPNext are open source under the GNU GPLv3 licence, so you can self-host, read the source, and extend them freely. Frappe Technologies also offers a paid cloud hosting product, but the framework itself carries no licence fee.

When should I not use Frappe?

Frappe shines for record-oriented business systems with forms, workflows, and reports. It is a poorer fit for real-time collaborative apps, heavy public-facing high-traffic sites that need edge caching over dynamic content, or products where you need total control of the database schema and request lifecycle. Match the tool to the shape of the problem.

Karani Geoffrey
Karani Geoffrey
Founder & CEO, Upeosoft

Karani Geoffrey is the Founder & CEO of Upeosoft, a software and automation company rooted in Kenya. He builds custom software, AI systems, and production-grade ERPNext for businesses across East Africa, and writes about the Kenyan realities - eTIMS, M-Pesa, SHIF, unreliable internet and power - that make or break real systems.

Next step

Want this working in your business?

Upeosoft builds and hardens the systems behind this article - for real Kenyan operations, with eTIMS, M-Pesa and offline realities handled.

Keep reading

For Builders

Why We Build on ERPNext/Frappe Instead of From Scratch

The engineering case for starting from ERPNext and Frappe rather than an empty repository: what you get for free, what it costs, and how to build custom software on top without painting yourself into a corner.

8 min readRead article →
For Builders

Building Offline-First Web Apps: Lessons From Kenya

How to build web apps that keep working when the network does not: service workers, IndexedDB, a durable sync queue, and conflict resolution, drawn from shipping software for real Kenyan connectivity.

8 min readRead article →
For Builders

How to Add AI to an Existing Business Application

A pragmatic engineer's guide to adding AI to software you already run: choosing a use case that pays off, using hosted APIs and retrieval over your own data, and building for cost, latency, and graceful failure.

8 min readRead article →