Loading

Working on Extension Code

Extension code runs inside the platform, on real data, frequently while somebody waits. That shapes how it should be written.

Where to find it

Architect Panel → Layout & Pages:

  • App Code — the in-browser editor

Architect Panel → Automation:

  • Extensions — the extension registry, its versions and runs

Architect Panel → Activity:

  • Error Log — where failures surface

Assume everything fails

External calls time out, values are missing, data is malformed, records are in states nobody anticipated. Code that assumes the happy path will meet all of these in its first month.

Handle failure explicitly rather than letting it propagate — and remember the fail mode setting decides whether your failure stops the operation or is skipped.

Be quick

Extensions run under a timeout, and frequently while a person waits. Anything slow — a large query, an external call, a loop over many records — belongs in a background task rather than in a hook attached to saving a record.

If you find yourself raising the timeout, that is usually a signal the work is in the wrong place.

Enforce permissions yourself

Custom code reaching data directly is not constrained by field security or row-level access unless you constrain it. If your extension returns or acts on something the triggering user should not see, that is a disclosure nothing else will catch.

Never embed credentials

They belong in the platform's credential storage. A secret in extension source is in your version history, in the platform's version history, visible to everybody with editor access, and awkward to rotate.

Only call allowlisted hosts

Outbound calls are restricted to hosts on the extension's allowlist. Design for that — and if you need a new host, add it deliberately rather than widening the list to something permissive.

Log enough to diagnose

When something goes wrong at three in the morning, what the log holds is what you have. Record what the extension was acting on, what it decided and what it received from anything external.

Do not log the data itself where it is personal — record identifiers and outcomes, not payloads.

Be idempotent where you can

Runs can be retried, and an extension that creates something each time it runs will create duplicates. Where the work is repeatable, make running it twice produce the same result as running it once.

Keep it small

An extension doing one thing is testable, reviewable and safe to change. One that has accumulated five responsibilities over three years is none of those, and nobody will want to touch it.

Worked example

An extension calling a supplier's API wraps the call with explicit timeout handling, logs the order reference and the outcome rather than the payload, takes its credential from platform storage, and is idempotent on the supplier's reference so a retry cannot double-book. It fails open, because a supplier outage should not stop order entry.

Recommendations

  • Handle failure explicitly — everything fails eventually.
  • Move slow work to a background task.
  • Check permissions in your own code.
  • Log identifiers and outcomes, not personal data.