Frappe Lets You Script Production From the Admin Screen. Here's Why You Shouldn't

Frappe's DocType builder, Server Scripts and Client Scripts make it easy to change a live system with no developer. Here's where that stops being safe, and what an experienced Frappe developer does di

Technical Solutions Architect
Published
Reading time
6 min read

Frappe makes it remarkably easy to change a running business system. Log in as an administrator, create a new DocType, add a Client Script to hide a field, add a Server Script to send an email on submit, and the change is live. No deployment, no terminal. Add an AI assistant that will write the Python and JavaScript for you, and it can feel as if you'll never need a developer at all.

For small adjustments, that's genuinely fine. That's what the low-code tools in Frappe are for. But I've reviewed enough Frappe and ERPNext sites to see where the approach breaks down: when the business logic that runs the company lives entirely in scripts typed or pasted into the admin screens of the production server. The problems aren't really about Frappe. They're about what happens to any software when nobody can see, test or reproduce how it changed.

This post is about where that line sits, and why it usually pays to hire someone experienced once you're past it.

What the admin screens are good for

To be fair to the tools, here's what's reasonable to do directly from the desk:

  • Adding a field or changing a label with Customize Form
  • A short Client Script that sets a default, hides a section or shows a message
  • A simple Document Event Server Script that validates one condition
  • Reports, print formats, workspaces and notifications

These are small, easy to understand, and easy to undo. If the person making them understands the business process, they're often the best person to make them.

Where it starts to go wrong

Changes live only in the database

When you create a DocType from the desk with "Custom?" checked, or write a Server Script or Client Script there, the definition is stored as a record in the site's database. It isn't a file in a code repository.

Frappe's own tutorial shows the alternative. With developer mode enabled on a development machine and "Custom?" unchecked, creating a DocType generates files inside your app: a .json definition, a .js form controller, a .py Python controller and a test file. Those files can go into version control, be reviewed, and be installed the same way on every site.

The database-only route means:

  • No history you can trust. Server Scripts do have a "Compare Versions" button, which helps. But there's no single place that shows what changed across the whole system last Tuesday, who changed it and why.
  • No staging. The change was made on production, so it was tested on production.
  • No clean rebuild. If you need a second site (a test environment, a new region, a restore after an incident), there's no reliable way to recreate exactly what's running except copying the whole database.

Server Scripts are deliberately limited

Since Frappe version 15, Server Scripts are disabled by default "to improve security on shared benches". On Frappe Cloud they need a private bench. When they are enabled, they run under RestrictedPython, which only allows a safe subset of methods.

Those restrictions exist for good reasons. In practice, though, logic that starts as a Server Script tends to hit the walls of the sandbox as it grows. Teams then work around the limits: chaining scripts together through frappe.flags, duplicating logic across several scripts, or moving calculations into Client Scripts where they're easier to write but trivially bypassed. A custom app has none of those limits and gets proper Python modules, imports and tests.

Nothing tests it

A DocType created in a custom app comes with a test file. A Server Script typed into a form comes with nothing. When an ERPNext upgrade changes a standard DocType or a framework API, the scripts are the first thing to break, and nobody finds out until a user reports that invoices stopped submitting.

Security mistakes are easy and quiet

Server Scripts can create API endpoints under /api/method/, with optional guest access. They can also define Permission Query scripts that decide which records a user can see. Both are powerful, and a single wrong condition can expose data to users, or to the public, who shouldn't have it. A reviewer with Frappe experience will usually catch this in minutes. A script pasted from an AI chat and saved straight to production gets no review at all.

Data models are expensive to change later

The hardest part of a Frappe build isn't the scripts. It's the DocType design: what's a DocType versus a child table, which fields are Links, how documents are named, what's submittable, how permissions follow the organisation. Get those wrong and every report, integration and script built on top inherits the mistake. Fixing it after a year of real data means migrations, not a few clicks.

AI assistants are fluent at producing a DocType definition for whatever you describe. They're much less reliable at the judgement calls: whether this should extend an existing ERPNext DocType rather than create a parallel one, how it'll be reported on, and what happens at ten times the volume.

AI-written Frappe code needs someone who knows Frappe

Frappe's APIs have changed between major versions, and an assistant doesn't always know which version you run. Code that looks right may call a method that behaves differently on your site, run a database query inside a loop on every save, or use ignore_permissions=True because it made an error go away. Someone experienced recognises these patterns immediately. Someone who doesn't know Frappe can't tell working code from code that only works today.

What an experienced developer does differently

The difference isn't that a developer writes cleverer scripts. It's that they set up a way of working where changes are visible and reversible:

  1. A custom app in a git repository holds the DocTypes, controllers, hooks and patches, so every change has a commit, an author and a reason.
  2. A development site with developer mode on, where DocTypes are designed and exported as files. Developer mode stays off in production.
  3. Fixtures for configuration. Frappe's fixtures are "database records that are synced using JSON files when you install and update your site". Custom Fields, Property Setters and similar records that started as desk customisations can be exported with bench export-fixtures and shipped with the app.
  4. A staging site that receives the same app version first, with a real data copy, before bench migrate runs on production.
  5. Tests and review for anything that touches money, stock, permissions or integrations.

None of this stops business users from using the low-code tools. It gives their good ideas a path into a system the company can maintain.

When hiring is cheaper than not hiring

It's tempting to compare a developer's day rate with "free" admin-screen changes. That comparison leaves out what the second path costs later: the outage after an upgrade, the weekend spent working out which of forty scripts sends the duplicate emails, the data leak through a guest API nobody remembered creating, the rebuild when the data model can't support the next requirement.

You don't necessarily need a full-time hire. For many small and mid-sized companies, the right shape is an experienced Frappe developer or architect who sets up the app, the environments and the rules, reviews changes, and handles the parts that need real engineering, while internal staff keep making small, safe changes through the desk.

A checklist for this month

1. Count what's in the database. Open the list views for Server Script, Client Script, Custom Field, Property Setter and DocType (filtered to custom ones). Write down how many of each there are and who created them.

2. Find the risky ones first. Look for API Server Scripts with guest access enabled, Permission Query scripts, and any script containing ignore_permissions. Get each one reviewed by someone who knows Frappe.

3. Decide where the line is. Write a one-paragraph rule: what's allowed directly in the desk (fields, labels, simple validations, reports) and what must go through the custom app and review (new DocTypes, integrations, permissions, anything touching accounts or stock).

4. Create a custom app if you don't have one. Put it in a git repository, even if it starts empty.

5. Move the important customisations into it. Export the critical Custom Fields, Property Setters and scripts as fixtures, or rewrite the larger Server Scripts as proper controllers and hooks with tests.

6. Set up a staging site. Run your next ERPNext or Frappe upgrade there first, with a recent copy of production data, before it touches the live system.

Sources


If your Frappe site has grown through admin-screen changes and you're not sure what's in it, a two-week discovery and audit sprint will map it and say what to move into code. Book a discovery call.

Written by Navil Shah

I help teams that build connected products get their telemetry, edge and cloud layers into shape — including what the CRA and Data Act now expect of them.