How to Create Reusable Custom Functions in Make: A JavaScript Tutorial

Introduction

You have the same date logic pasted into fourteen scenarios: a chain of routers, iterators, and filters that counts working days for an SLA deadline. Then the business changes the rule, and you get to edit it fourteen times. That is the failure custom functions exist to fix: one JavaScript function, written once, called from any mapping in any scenario on your team.

This tutorial builds a reusable working-days function, calls it from a real scenario, breaks it on purpose, and rolls it back with version history.

Quick answer

In Make, open Functions in the left sidebar, click Add a function, write synchronous JavaScript ES6 under 5,000 characters, save it, and call it by name from any mapping field in the scenario designer.

The hard part is not writing the JavaScript, it is respecting the sandbox: no HTTP requests, no async code, no recursion, and a 300 millisecond limit, so the function has to be small, pure, and fast.

Checked on 2026-11-10 against the Make Help Center custom functions page and the Make blog post on custom functions best practices. Interfaces change fast, if a menu or label differs, trust the linked page.

Evidence

Custom functions launched on 2026-10-20 as part of Make’s Waves release. Make’s own launch post states the case plainly: “Custom Functions allow Make Enterprise customers to perform multiple actions within a single step in a workflow using JavaScript, which extends Make’s capabilities beyond the available pre-built actions.” The same post gives the clearest before-and-after number: one team cut an address-parsing flow from 10 to 12 modules down to just 1 to 2 by moving the parsing logic into a custom function.

The limits are the other half of the evidence: a single function cannot run for more than 300 milliseconds, its code cannot exceed 5,000 characters, and Make does not validate your code before you save it. Errors only appear when a scenario that uses the function runs, which is why the debugging and rollback steps below matter more than the writing step.

Prerequisites

  • A Make account on the Enterprise plan. Custom functions do not exist on Core, Pro, or Teams, and the Functions section simply does not appear there.
  • The Team Admin role in your team. Team Members can view and use custom functions, but only a Team Admin can create or edit them.
  • Basic JavaScript, ES6 syntax: functions, loops, Date, and return. No third-party libraries are supported, so everything must be plain JavaScript.
  • A scenario where you already repeat the same transformation, so you have somewhere real to call the function from.

Step-by-step guide

Step 1. Open the Functions section

In the left sidebar, click Functions. If your sidebar is collapsed, click the three dots and then Functions. This section lists every custom function that belongs to your team. If you do not see it, you are either not on Enterprise or not signed in with a Team Admin account.

Step 2. Create the function shell

Click Add a function. Enter a Name and a Description. The name is what your teammates will see in the scenario designer, so name it for what it returns, not how it works: numberOfWorkingDays, not dateHelperV2. The description should state the inputs, the output, and one limitation. Click Save. The function is now listed, but it has no code yet.

Step 3. Write the working-days function

Make’s own documentation ships a numberOfWorkingDays(month, year) example, and it is the right starting point. Paste this version into the code editor, which is the docs example with one fix applied (explained in the next paragraph):

function numberOfWorkingDays(month, year) {
  let counter = 0;
  let date = new Date(year, month - 1, 1);
  const endDate = new Date(date.getFullYear(), date.getMonth() + 1, 0);
  while (date.getTime() <= endDate.getTime()) {
    const weekDay = date.getDay();
    if (weekDay !== 0 && weekDay !== 6) {
      counter += 1;
    }
    date = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1);
  }
  return counter;
}

We tested this code in Node.js before publishing. For November 2026 it returns 21, which is correct: November 2026 has 30 days starting on a Sunday, so 21 weekdays. Note the <= in the while condition. The documentation’s example uses <, which stops the loop before the last day of the month. November 30, 2026 is a Monday, so the docs version returns 20 and silently drops one working day, a small bug with a real consequence for an SLA deadline. If you copy the example from the docs, change < to <= and test it.

Click Save. The function is immediately available in the scenario designer, marked with a small person icon.

Step 4. Call it from a scenario mapping

Open any scenario and click into a mapping field, for example the field where you set a due date or a day count. Open the functions list and pick numberOfWorkingDays. It appears alongside the built-in functions, with the person icon. Map the arguments from your scenario data, for example the month and year from a trigger, and the returned number flows into the field like any other mapped value. There is no extra module to add and no extra operation to pay for, the function runs inside the mapping.

We could not verify the exact click path inside the scenario designer against a live Enterprise account, because the Functions section requires an Enterprise plan and a Team Admin role, and our lab has neither. The Help Center states the function “immediately becomes available in the scenario designer” after the first save, and that is the behavior this step relies on.

Step 5. Test it in the debug console before trusting it

Under the code editor sits a debug console. Run your function there with real inputs before any scenario depends on it: numberOfWorkingDays(11, 2026) should return 21, and numberOfWorkingDays(2, 2026) should return 20, since February 2026 has 28 days starting on a Sunday. Make does not validate your code when you save it, so the debug console is the only check between you and a broken scenario.

Step 6. Break it on purpose, then watch how it fails

Deliberately write a version that violates a limit, for example one that calls fetch() to look up public holidays. Save it, then run the scenario. The run fails, and the error tells you the mapping failed, not which rule you broke. This is the failure mode to internalize: a custom function error surfaces as a scenario execution error, and the scenario stops. The fix is to move the HTTP call out of the function and into an HTTP module, then pass the result in as an argument. Functions transform data, modules fetch it.

Step 7. Roll back with version history

Every save creates a new history record. Open the function, switch to its History tab, select a record to compare it with the previous version (you can only compare two consecutive versions), and click Restore this version. Restoring creates a new version with the old content, so the history itself is never rewritten.

flowchart TD
    A[Enterprise plan + Team Admin role] --> B[Open Functions in the left sidebar]
    B --> C[Add a function: name + description]
    C --> D[Write JavaScript ES6, under 5000 chars]
    D --> E[Test in the debug console]
    E --> F{Tests pass?}
    F -->|No| D
    F -->|Yes| G[Save: function goes live in the scenario designer]
    G --> H[Call it from any mapping field]
    H --> I[History tab restores earlier versions]

Flow of creating a reusable custom function in Make, from the steps above. The Simular Box screenshot for this article could not be taken: the box failed to wake twice on 2026-11-10 (state “failed”), so this diagram replaces the screenshot rather than delaying publication.

Copy-paste template

The function below is the original deliverable for this article: a businessDaysBetween(start, end) function that counts working days between two dates, inclusive on both ends. It is the version you actually want in production, because most deadlines are a range, not a month number. We verified it in Node.js: businessDaysBetween("2026-11-02", "2026-11-06") returns 5, a pure weekend range returns 0, and an invalid date returns the string “Invalid date” instead of crashing. It is 613 characters, far under the 5,000 character limit. Example values below are placeholders, replace them with your values.

function businessDaysBetween(start, end) {
  const startDate = new Date(start);
  const endDate = new Date(end);
  if (isNaN(startDate) || isNaN(endDate)) {
    return "Invalid date";
  }
  if (endDate < startDate) {
    return 0;
  }
  let count = 0;
  const cursor = new Date(
    startDate.getFullYear(), startDate.getMonth(), startDate.getDate()
  );
  const last = new Date(
    endDate.getFullYear(), endDate.getMonth(), endDate.getDate()
  );
  while (cursor.getTime() <= last.getTime()) {
    const day = cursor.getDay();
    if (day !== 0 && day !== 6) {
      count += 1;
    }
    cursor.setDate(cursor.getDate() + 1);
  }
  return count;
}

Two details are deliberate. First, <= in the loop, so the end date itself is counted, the same off-by-one fix as Step 3. Second, the invalid-date guard returns a readable string instead of NaN, because a NaN flowing into a downstream module is much harder to diagnose than the words “Invalid date”. Neither function accounts for public holidays, and there is no holiday calendar inside the sandbox. If your SLA excludes holidays, pass a holiday list in as an argument or check the dates in a module first.

When not to use this / Limits

Do not use custom functions for anything that needs the network, the clock beyond a simple date, or more than 300 milliseconds of compute. If your logic fetches data, waits, retries, or loops over thousands of records, it belongs in a module, not in a function. Do not use them as a private code library for a whole team either: functions cannot call each other, so shared helpers must be duplicated, and a 5,000 character ceiling keeps every function small by design. If you are not on Enterprise, use the built-in functions in the mapping panel, or a Make MCP server setup that lets an AI assistant compose the same transformations. And if nobody on your team reads JavaScript, do not adopt custom functions: the person who debugs them at 3 a.m. will be the person who wrote them.

Cost / scale math

Take the address-parsing example from Make’s blog: a flow that needed 10 modules per run becomes 1 module that calls a custom function inside a mapping. Assume 100 runs a day, a modest volume for an order flow. Before, that is 10 modules times 100 runs, or 1,000 operations a day. After, it is 1 module times 100 runs, or 100 operations a day, a saving of about 900 operations a day, or roughly 27,000 a month, from one function. Example, replace with your values. The assumption is that the function call adds no module operation, which follows from how Make describes it: the work happens inside a single module operation. The saving scales with runs, so the best candidates are the transformations your busiest scenarios repeat.

Troubleshooting

SymptomLikely causeCommand to checkFix
Scenario fails with a mapping error right after you save a functionThe function has a JavaScript error, and Make does not validate code on saveRun the function in the debug console under the code editorFix the error in the console, save, and rerun the scenario
Function returns a count that is one day shortThe loop uses < instead of <= against the end date, so the last day is never countedRun numberOfWorkingDays(11, 2026) in the console, it should return 21Change the condition to <= and retest
Scenario fails with “Function ‘’ not found!”Someone deleted a custom function the scenario usesOpen Functions, check the History tab and the Scenarios tab of the deleted functionRestore the function from history, or remap the field to a replacement
Function silently returns nothing usefulAn async call, fetch(), or recursion is in the code, which the sandbox forbidsRead the function for await, fetch, XMLHttpRequest, or a self-callMove the network call to an HTTP module and pass the result in as an argument

Common mistakes

  • Copying the docs example without testing it. The official numberOfWorkingDays example undercounts by one working day because its loop stops before the last day of the month. Always run a new function in the debug console with a month you can verify by hand.
  • Treating the function like a module. A function cannot fetch data, wait, or call another function. If your logic needs an API response, fetch it in a module first and pass the value in as an argument.
  • Using the function with an Iterator directly. To use a custom variable with an Iterator, set the value with the function in a Set Variable module before the Iterator, then map the Set Variable output into the Iterator. Calling the function inside the Iterator mapping does not work the way you expect.
  • Deleting a function without checking where it is used. Open the function’s Scenarios tab first. Deleting a function that a scenario depends on breaks that scenario on its next run, and the error message names the function, not the person who deleted it.

Test before you rely on it

  • Run the function in the debug console with at least three inputs you can verify by hand, including a month that ends on a weekday.
  • Run the full scenario end to end and confirm the mapped value lands in the destination field, not just that the scenario turns green.
  • Delete nothing. Instead, open the History tab and confirm you can see the previous version and restore it.
  • Check the organization time zone against the time zone of your incoming dates, and run one test with a date near midnight.
  • Confirm a Team Member can see and use the function in the scenario designer, and cannot edit it, so the permission boundary works as documented.
  • Simulate a bad edit: change one line, save, confirm the scenario fails, restore from History, and confirm it passes again.

FAQ

Two more worth answering: can you share a function with another team? No, functions belong to a team, so a second team needs its own copy. And can you test against production data safely? Yes, use the debug console with pasted production values, or clone the scenario and point the clone at test data.

Conclusion

Custom functions are a small feature with an outsized payoff, but only for teams that respect the sandbox. One function replaces a chain of modules, one edit fixes every scenario that calls it, and one history record undoes a bad edit. The trap is treating it like a general-purpose code runner: the sandbox will not warn you, it will fail your scenario at runtime.

Ask yourself this before your next scenario: is there a transformation you have already built twice? If yes, write it once as a custom function, test it in the console, and delete the copies. To go further, read our guide to reusable AI agents and team sharing in Make, and for the self-hosted alternative, the n8n complete guide.

Frequently asked questions

Do I need the Enterprise plan to use custom functions in Make?

Yes. Custom functions are an Enterprise-only feature. They belong to a team, every Team Member can view and use them, and only a Team Admin can create or edit them. If you are on Core, Pro, or Teams, the Functions section does not appear.

Can a custom function call an API or another custom function?

No. Custom functions cannot make HTTP requests, cannot call other custom functions, cannot use recursion, and cannot run asynchronous code. They run synchronously on Make's servers, in at most 300 milliseconds, with at most 5,000 characters of code.

What happens if I delete a custom function that a scenario uses?

The scenario fails on its next run with the error "Failed to map '<field name>': Function '<function name>' not found!" Check the Scenarios tab of the function before deleting it to see every scenario that depends on it.

Can I use Make's built-in functions inside a custom function?

Yes. Built-in functions are available as methods of the iml object, for example iml.length(text). This is the documented way to reuse built-in logic instead of reimplementing it in JavaScript.

Do custom functions cost extra operations?

A custom function runs inside a mapping, so calling it does not add a module to your scenario and does not add a module operation. Make's own blog puts it this way: custom functions let you take more actions within a single module operation, which is where the operation savings come from.

How do dates work inside a custom function?

Custom functions run on Make's servers, so dates inside a function use the time zone set for your organization, not your browser's time zone. Keep that in mind when a function computes deadlines across teams in different time zones.

TP
ToolPilot Team

We install, break, and fix automation tools so you don't have to. Every tutorial on ToolPilot is tested hands-on before publishing.

Keep reading