Regeneration-first development for apps that change safely
Learn regeneration-first development to keep apps flexible: update data, logic, and UI while regenerating clean code instead of patching.

Why patching changes turns into technical debt
Patching is what happens when a new requirement shows up and you squeeze it into the app with the smallest possible edit. It feels fast because it is. The problem is that each patch is a local fix, and local fixes rarely match how the app should be structured.
Over time, patches stack up. The app still runs, but the code and configuration start to disagree: the database suggests one thing, the UI implies another, and the real rules live in three different places. That mismatch is technical debt. It is not just "bad code". It is the growing cost of making the next change.
You can usually spot it:
- Logic gets tangled, so one small rule change touches many screens or endpoints.
- Fields get duplicated ("status", "ticket_status", "status_v2") because renaming feels risky.
- UI becomes fragile, with hidden dependencies on specific data shapes or edge cases.
- Workarounds turn into "temporary" flags that never go away.
- Fixes need follow-up fixes because nobody is sure what else might break.
The painful part is how quickly risk grows. A change that should be small (add an approval step, adjust a pricing rule, split one user role into two) turns into a risky release because you cannot predict the blast radius. Testing becomes guesswork. Rollback gets harder because the patch touched unrelated parts.
Regeneration-first development is a direct response to that. The goal is to structure your app so changes are predictable and reversible, and so the platform can regenerate clean code without carrying forward yesterday's hacks.
A practical target:
- One clear source of truth for data (no duplicate "almost the same" fields).
- Rules live in one place, not sprinkled across UI and endpoints.
- UI focuses on display and input, not business decisions.
- Changes happen in the model and logic, then you regenerate, rather than hand-editing outputs.
Platforms like AppMaster support this because the app is defined by models and visual logic, and the platform regenerates full source code. Regeneration stays clean only if you avoid patch-driven structure in the first place.
What regeneration-first development means
Regeneration-first development treats your app as a set of clear models, not a pile of hand-edited code. You change the models, regenerate, and get a fresh, consistent version of the app. The point is to ship changes without leaving behind extra hacks that make the next change harder.
In a patch-first workflow, a small request (a new status field, a new approval step) gets added wherever it fits fastest. Someone tweaks one API handler, updates one screen, adds a special case somewhere else, and moves on. The app works today, but the logic is now scattered. After a few cycles, nobody is sure where the real rules live.
With regeneration-first development, the source of truth stays in the models:
- Data model: entities, fields, relations, constraints
- Business logic model: the rules and flows that decide what happens
- UI model: screens, components, and how they bind to data
Everything generated from those models (API endpoints, database access, web and mobile code) is output, not a place for quick fixes.
In AppMaster, that output can include Go for the backend, Vue3 for the web app, and Kotlin or SwiftUI for mobile. When requirements change, you update the model once and regenerate, instead of hunting down the same rule across multiple files.
This keeps the app consistent across layers because the same definitions drive every part. If "Ticket Status" becomes required, the database schema, validation, API, and UI bindings should update together. If an approval rule changes, you update the process so every endpoint and screen reflects the same logic.
The mindset shift is simple: edit what you mean (models), generate what you need (code).
Build a data model that can evolve
If you want regeneration-first development to work, start with the part that should change the least: the data model. Change-friendly apps survive feature requests not because every screen is perfect, but because the core entities are stable and well named.
Begin with the nouns your business will still use a year from now. For many apps that means User, Account, Team, Ticket, Order, Invoice, Product, or Message. When those are clear, everything else (workflows, permissions, UI) has a solid base.
Naming is not a minor detail. It prevents later changes from turning into confusing migrations and broken logic. Pick singular names for entities, use consistent field names (created_at vs createdAt), and choose types that match reality (money as decimal, timestamps with timezone rules you agree on). Small inconsistencies spread into rules, filters, and reports.
Plan for growth without overdesign. You do not need to predict every future field, but you can make common change types safer:
- Prefer status fields that can accept new values instead of adding a new table for every stage.
- Use optional fields for data that is not always present (phone_number, external_id).
- Add audit fields early (created_at, updated_at, created_by) so you are not retrofitting later.
- Keep "notes" and "metadata" separate from core fields so experiments do not pollute the main model.
A visual data designer helps because you can see relationships and constraints before they become code. In AppMaster, the Data Designer maps your schema to PostgreSQL, so you can model tables, fields, and links in one place and regenerate clean source code when requirements shift.
Example: a support portal starts with Tickets linked to Accounts and Users. Later the business asks for priority, category, and a new status called "Waiting on Customer". If Tickets already have a status field and optional fields for details, you can add values and fields without redesigning the database. The regenerated app keeps queries and APIs consistent, and you avoid a pile of one-off patches.
The goal is readability today and forgiveness tomorrow.
Make business logic modular and readable
Business logic is where change usually breaks things. A quick fix that "just works" today can turn into a web of special cases tomorrow. With regeneration-first development, you design logic so it can be regenerated cleanly, without relying on patches that only make sense in someone's head.
A practical approach is to treat every workflow as a set of small blocks. Each block does one job: validate inputs, calculate a price, decide a route, send a message, update a record. In AppMaster this maps naturally to the Business Process Editor. Smaller processes are easier to read, test, reuse, and replace.
Think in inputs and outputs
Before you build a block, write down two things: what it needs, and what it returns. If you cannot describe that in one sentence, the block is probably doing too much.
Good blocks have clear boundaries. They take explicit inputs (user role, ticket status, order total) and return explicit outputs (approved or denied, final price, next step). That clarity makes changes safer because you can swap one block without guessing what else it affects.
A quick checklist:
- One purpose per block (validation or calculation or routing)
- Inputs are passed in, not "found somewhere"
- Outputs are returned, not hidden in side effects
- Names describe outcomes (like
ValidateRefundRequest) - Errors are handled consistently
Avoid hidden dependencies
Hidden dependencies make logic fragile. If a workflow relies on global flags, silent state changes, or "this variable is set earlier somewhere," small edits can change behavior in ways you do not expect.
Pass state through the process on purpose. If something must be stored, store it in an obvious place (like a database field) and read it explicitly. Avoid "magic" behavior like changing a record in one step and assuming another step will notice.
Make decision points visible. For example, a support portal might branch on "Is this ticket VIP?" and "Is it after business hours?" If those branches are clear and labeled, a future change like "VIP rules changed for weekends" is a quick edit, not a risky rewrite.
Separate UI concerns from rules and data
A change-friendly app is easiest to regenerate when the UI stays "dumb". Screens should collect input, show state, and guide the user. When business decisions are hidden inside buttons, validations, and one-off screen logic, every new requirement turns into a patch.
Treat the UI as a thin layer over shared rules and data. Then the platform can rebuild the presentation cleanly without re-implementing decisions in ten places.
Where UI ends and business rules begin
A practical split is: UI handles clarity; business logic handles truth. UI can format, label, and help users. Business logic decides what is allowed and what happens next.
UI responsibilities often include:
- Displaying data and collecting user input
- Formatting (dates, currency, phone masks)
- Basic required-field checks (empty vs not empty)
- Showing errors returned by logic in plain language
- Navigation and layout
Business rules should live outside the screen, for example in a workflow or process editor: "refund requires manager approval", "VIP customers skip the queue", "ticket cannot be closed without a resolution code". Keep those rules tied to the data model, not to a specific page.
Design once, reuse across web and mobile
If you support more than one client (web plus native mobile), duplication causes drift. Reuse shared components for common patterns (ticket status badge, priority selector, customer card), but keep behavior consistent by feeding them the same data and the same rule results.
For example, you can model ticket states in the data designer, drive state changes through a single business process, and have both web and mobile UIs call that process and render the returned state. When "Escalated" becomes "Urgent review," you update it once and regenerate rather than hunting down hidden conditions in each screen.
A good test: if you removed a screen and rebuilt it tomorrow, would the app still enforce the same rules? If yes, the separation is working.
Step by step: structure an app for clean regeneration
Regeneration-first development works best when your app is split into clear parts that can change independently. Think in modules first, not screens.
Name the core modules and keep them separate in your head and in your work: data (tables and relations), processes (logic), API (endpoints), web UI, and mobile UI. When a requirement changes, you should be able to point to what changes and what should stay untouched.
A build order that stays change-friendly
Use a small loop and keep each step modest:
- Model the data first: entities, fields, relationships that match reality.
- Add business processes as reusable flows. Make each process do one job (Create Ticket, Assign Agent, Close Ticket).
- Connect processes to API endpoints after the logic is readable. Treat endpoints as a wrapper around your flows, not a place to hide rules.
- Build UI screens around user tasks, not around database tables.
- Regenerate and test after every small change.
Small example: changing requirements without messy patches
Say you are building a support portal in AppMaster. The first version has Tickets and Comments. A week later the business asks for Priority and a new rule: VIP customers always start as High.
With a modular structure, you change the data model (add Priority), update one business process (Create Ticket sets Priority based on customer type), regenerate, and verify the same UI task still works. No scattered fixes across multiple screens.
A simple habit helps: after each regeneration, quickly run the key flows end to end (create, update, permission check) before you add the next feature.
Example: a customer support portal that keeps changing
Picture a small support portal. Customers log in, see their tickets, open a ticket to view details, and add a reply. Support agents see the same tickets plus internal notes.
A regeneration-first approach separates three things: the ticket data model, the business processes (how tickets move), and the UI screens. When those parts are clear, you can change one without patching around the others.
Start simple, but structure it for change
The first version can be minimal:
- Data: Users, Tickets, Messages
- Processes: Create ticket, Reply, Assign to agent
- UI: Ticket list, Ticket details, New ticket form
In AppMaster, this maps cleanly to a PostgreSQL-backed data model (Data Designer), a drag-and-drop workflow for rules (Business Process Editor), and separate web and mobile UI builders.
Change 1: add priority and SLA dates
Product asks for Priority (Low, Normal, High) and an SLA due date. With regeneration-first structure, you add fields to the Ticket model, then update only the places that read or write those fields: the create-ticket process sets a default priority, the agent screen shows the SLA due date, and the list screen adds a filter.
The platform regenerates the backend and API so the new fields become first-class parts of the code.
Change 2: add an approval step before closing
Now closing a ticket needs manager approval for certain customers. Instead of sprinkling close rules across multiple screens, you add a clear state to the model (Open, Pending approval, Closed) and update the close process:
- Agent requests close
- System checks whether approval is required
- Manager approves or rejects
- Ticket closes only after approval
Because the rule lives in one process, the UI shows the current status and the next allowed action.
Change 3: mobile push notifications
Finally, users want push notifications when an agent replies. Do not bury notification logic in UI code. Put it in the "New message" process: when a reply is saved, trigger a notification module. Regeneration then produces updated native apps without turning changes into manual patchwork.
Common mistakes that break regeneration-first workflows
Regeneration-first development works only if your app stays regeneratable. Teams usually break it with quick fixes that feel harmless today, but force workarounds tomorrow.
1) Editing generated code instead of changing the model
Mixing generated parts with manual edits in places that get overwritten is the fastest way to lose clean regeneration. If you are using a platform that generates real source code (like AppMaster does for backend, web, and mobile), treat the visual project as the source of truth. When a requirement changes, update the data model, business process, or UI builder.
A simple rule: if you cannot reproduce the change by regenerating from the visual project, it is not a safe change.
2) Letting the UI decide the rules
When screens encode business rules ("this button shows only for VIP users", "this form calculates totals in the UI"), every new screen becomes a special case. You end up with hidden logic that is hard to update consistently.
Keep validations, permissions, and calculations in business logic (for example, in a Business Process), then let the UI display the result.
3) Designing a fantasy data model too early
Over-modeling looks like adding dozens of fields, statuses, and edge-case tables before you have real usage. It makes change painful because every update touches too many parts.
Start with what you know, then expand in small steps:
- Add only fields you can explain in plain language.
- Keep status values short and real (3-6, not 20).
- Prefer adding a new table later over cramming meaning into one giant table.
4) Skipping naming conventions
Inconsistent names create confusing models and endpoints: "Cust", "Customer", and "Client" in one app. Regeneration still works, but humans make mistakes during changes.
Pick a simple pattern early (singular table names, consistent verbs for actions) and stick to it.
5) Building one giant workflow
One huge workflow feels tidy at first, then becomes hard to change safely. Break logic into small processes with clear inputs and outputs. In a support portal, separate "Create ticket", "Assign agent", and "Send notification" so you can change one step without risking the rest.
Quick checks before regenerating and shipping
Regeneration-first development feels safe only when you have a routine that catches common "silent break" problems. Before you regenerate, do a short pass that matches how your app is structured: data, logic, UI, and APIs.
A fast checklist:
- Data: entities and fields match current requirements, names are consistent, and you are not keeping two fields that mean the same thing.
- Logic: each workflow has a clear input, clear output, and a predictable error path.
- UI: screens reuse shared components and do not hard-code rules.
- APIs: endpoints map to workflows consistently. You can answer "Which workflow powers this endpoint?" without digging.
- Release: you have a small, repeatable test script, not "click around until it looks fine".
Keep a single source of truth for rules. If ticket priority depends on customer tier, define it in one workflow and have both the API and UI reflect it.
A 10-minute test script that mirrors real use is usually enough:
- Create a new record with required fields only.
- Trigger the main workflow and confirm the expected status change.
- Try one known error case (missing permission or missing required data).
- Open key screens on web and mobile and confirm the same rule shows up the same way.
- Call one or two core endpoints and confirm responses match what the UI shows.
If anything fails, fix the structure first (data, workflow, shared UI) and regenerate again.
Next steps: apply this approach on your next change
Pick one area to improve first and keep the scope small. If recent changes have been painful, start with the part that caused the most rework: the data model, a tangled piece of logic, or a screen that keeps getting "just one more tweak".
Treat the next change as a drill: adjust, regenerate, verify, ship. The goal is for updates to feel routine, not risky.
A simple loop to repeat:
- Make one small change (one field, one rule, or one screen behavior).
- Regenerate so the code stays consistent.
- Run a quick smoke test (happy path plus one edge case).
- Deploy to a safe environment first (staging or a test workspace).
- Ship and write down what you learned.
Keep a short change log that explains decisions, not just edits. For example: "We store ticket priority as an enum, not free text, so reports do not break when labels change." Two lines like that can save hours later.
If you want to practice this without hand-editing generated output, build a small, contained module in AppMaster (for example, a ticket form, an admin list, or a simple approval step), regenerate after each change, and pay attention to how much easier it is to evolve the app when the model stays the source of truth. If you are evaluating tools, appmaster.io is a straightforward place to start experimenting with that workflow.
Your next change is a good time to start. Choose one corner of the app and make it change-friendly today.
FAQ
Patching is when you squeeze a new requirement in with the smallest possible change. It feels fast, but it often creates mismatches between the database, API, logic, and UI, which makes the next change slower and riskier.
Technical debt is the extra cost you pay on future changes because today’s structure is messy or inconsistent. It shows up as longer implementation time, higher risk of regressions, and more testing and coordination for changes that should be simple.
Common signs are duplicated fields that mean almost the same thing, business rules scattered across UI and endpoints, and “temporary” flags that never get removed. You also see small rule updates touching many unrelated places because nobody trusts the boundaries.
Regeneration-first means you edit the models that describe your app (data, logic, UI) and then regenerate the output (backend, APIs, clients) from those definitions. The goal is that changes are predictable because the source of truth stays centralized and consistent.
Treat the visual project (models and processes) as the source of truth and the generated code as output. If you make manual edits inside generated areas, you’ll either lose them on regeneration or avoid regenerating, which pulls you back into patch-first habits.
Start with stable nouns your business will keep using, and name them clearly and consistently. Use types that match reality, add audit fields early, and avoid duplicating meaning across fields so you don’t end up migrating your way out of confusion later.
Break logic into small processes where each block has clear inputs and outputs. Pass state explicitly instead of relying on hidden flags or “something set earlier,” so you can change one rule without guessing what else will break.
Keep UI focused on display and input, and keep business rules in shared logic (like a workflow or process). The UI can show what’s allowed, but the backend logic should decide what’s true, so rules don’t drift across screens and clients.
Use a simple order: model data, build readable processes, wrap them with endpoints, then build UI around user tasks. After each small change, regenerate and run a short end-to-end smoke test so you catch silent breaks before they compound.
It works best when requirements change often and you support multiple clients (web and native) that must stay consistent. If you want a no-code way to practice this, AppMaster lets you define data models, build logic visually, and regenerate full source code so changes don’t rely on one-off patches.


