Tips > Building Workflows

Create Reusable Utility Functions at the Top of Code Nodes

When your Code node grows beyond 20-30 lines, organize it by defining utility functions at the top.

When a Code node grows past 20-30 lines, define utility functions at the top of the node. This keeps the main logic readable and lets you reuse parsing, formatting, and validation helpers within the same node. Call the helpers from a single map over the incoming items to produce clean, normalized output.

What are reusable utility functions in a Code node?

When your Code node grows beyond 20-30 lines, organize it by defining utility functions at the top. This makes the main logic readable and lets you reuse parsing, formatting, and validation logic within the same node.

Real-world example: A data sync workflow processes contact records that need phone number normalization, email validation, and name formatting before upserting to a CRM.

How do you structure a Code node with utility functions?

// Mode: Run Once for All Items

// --- Utility Functions ---
function normalizePhone(raw) {
  if (!raw) return null;
  const digits = raw.replace(/\D/g, '');
  if (digits.length === 10) return `+1${digits}`;
  if (digits.length === 11 && digits.startsWith('1')) return `+${digits}`;
  return digits.length >= 10 ? `+${digits}` : null;
}

function isValidEmail(email) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email ?? '');
}

function titleCase(str) {
  if (!str) return '';
  return str.toLowerCase().replace(/\b\w/g, c => c.toUpperCase());
}

function buildFullName(first, last, company) {
  const name = [first, last].filter(Boolean).map(titleCase).join(' ');
  return name || company || 'Unknown';
}

// --- Main Logic ---
return $input.all().map(item => {
  const c = item.json;
  return {
    json: {
      fullName: buildFullName(c.firstName, c.lastName, c.company),
      email: isValidEmail(c.email) ? c.email.toLowerCase().trim() : null,
      phone: normalizePhone(c.phone),
      company: c.company?.trim() || null,
      isValid: isValidEmail(c.email) && !!normalizePhone(c.phone),
    }
  };
});

If you find yourself copying utility functions across workflows, consider creating a shared Code node at the start of your workflow that attaches helpers to $workflow static data (see n8n's static data feature).

When should you extract utility functions?

  • The node's logic has grown beyond 20-30 lines and is hard to read.
  • You repeat parsing, formatting, or validation logic within the same node.
  • You reuse the same helpers across workflows -- attach them to $workflow static data.

Related: Use Edit Fields in "Map Each" Mode for Simple Renames · Configure Payload Size and Binary Data Mode for Large Files

Showcase builds

19 complete workflows from my own projects, each with its n8n workflow JSON to import. Showcase entries link the file at the end of the article.

See the showcase builds

Keep reading

190 entries grouped by topic, from first workflow to queue mode. Free, no signup.

Browse the encyclopedia

Need it built?

I design, build and run n8n systems for clients. Every engagement starts with a $1,500 diagnostic audit, credited toward the build.

Book an introductory call