[object Object]

The custom app worked great in dev. Then production added the second tenant, the upgrade landed, and the security review surfaced. The patterns that take a custom app from “it works” to “it survives operations” are deceptively boring — scope, table inheritance, security model, test coverage — and getting them wrong on day one is what guarantees a rewrite by year three.

Scope Everything

Never build a custom app in global scope. Create an application scope with a meaningful prefix (x_acme_inventory, not u_). Tables, scripts, ACLs, UI components, business rules — all live in the scope. Clean packaging, clean install, clean removal, predictable behavior under upgrade. Global-scope custom artifacts are the most reliable source of post-upgrade breakage and the hardest to clean up after the original developer has left.

Scoped app artifact ownership:
  x_acme_inventory.tables[*]
  x_acme_inventory.script_includes[*]
  x_acme_inventory.acls[*]
  x_acme_inventory.ui_pages[*]
  x_acme_inventory.system_properties[*]

Table Design

Extend the right parent table when extending makes sense; create freestanding tables when it does not. Extending task gives you SLA support, notification engine, workflow integration, assignment fields, work notes, and audit history for free. Extending sys_metadata does not give you those — it makes the records system metadata that participates in update sets, which is rarely what an application table should do. Choose parent tables consciously and document the choice.

Business Rules vs Flows

Use Flow Designer or Workflow Studio for cross-entity workflows and asynchronous processes — orchestration of multiple records, integrations with external systems, time-based triggers. Use business rules for record-level invariants — validation that must run on every save, default value computation, computed-field maintenance. Mixing them produces logic that is hard to trace; a record updated by a flow that triggers a business rule that triggers another flow is the classic spiral.

// Business rule: record-level invariant only
(function executeRule(current, previous) {
  if (current.status == 'closed' && current.resolution_code.nil()) {
    current.setAbortAction(true);
    gs.addErrorMessage('Resolution code is required to close.');
  }
})(current, previous);

Security Model

Define roles per persona — x_acme_inventory.user, x_acme_inventory.approver, x_acme_inventory.admin. Assign ACLs to roles, not directly to users. When a single role becomes the shortcut for admin-equivalent access, the model is over-scoped and needs decomposition. Test the security model with a deliberate negative case: a user without the required role attempts the operation; the operation fails at the ACL level, not just hidden in UI.

Testing and ATF

Every custom app should ship with an ATF test suite. Minimum coverage: happy-path record creation, the most important validation rule, and a security check (an unauthorized user is denied). ATF runs in CI via MID Server integration; failing tests block the deployment. Apps without ATF tests accumulate hidden regressions; the upgrade audit will find them, usually at the worst time.

Common Failure Modes

Tables created with u_ prefix in global scope and never moved — the app cannot be cleanly uninstalled and updates leak across instances. Business rules that call REST endpoints synchronously — every save blocks on the network, the app gets slow, the user blames the platform. Use async flows for outbound calls. UI Pages built with Jelly when UI Builder is the strategic path — Jelly works but the upgrade roadmap is converging on UI Builder; new work should target the strategic platform.

What Changed in 2026

Workflow Studio is the strategic flow authoring surface as of the Zurich release. New custom apps should target it; existing apps on Flow Designer continue working but new flows in those apps should follow the migration guidance. App Engine Studio’s policy engine for citizen-developer apps now applies to professional-developer apps too, with stricter enforcement options.

Implementation Sequence

Stand up the scoped app shell first (scope, base tables, roles, ACL skeleton, baseline ATF). Validate the security model with a negative test before any business logic ships. Then layer in business rules, then flows, then UI. Building UI before security is how apps reach production with broken access control nobody noticed.

What to do this week: pick one custom app you maintain and verify it has at least one ATF test for the security model; if not, that is your next sprint task.

[object Object]
Share