What breaks when you move Pipedream code steps to n8n Cloud
Updated October 13, 2026
On n8n Cloud, the Code node can only load two modules, crypto and moment, and Python code can't import anything, not even the standard library (n8n Code node docs). Pipedream code steps that import axios, date-fns, an SDK or any other npm package fail until you replace them with n8n built-ins like this.helpers.httpRequest and Luxon, or move to self-hosted n8n with NODE_FUNCTION_ALLOW_EXTERNAL. Pipedream's own helpers (steps, $.export, $.respond, data stores, process.env) also need n8n equivalents.
Pipedream Workflows has been in maintenance mode since September 30, 2026 and stops running on March 31, 2027, so every code step needs a new runtime by then. The npm limit is the part that takes the most time, because Pipedream made npm free to use: you wrote import axios from "axios" and Pipedream installed it on deploy (Pipedream Node.js docs). One person reviewing real Pipedream exports in the n8n community forum put it this way: "About 7 in 10 of the code steps I looked at import a package or call an API" (n8n community).
Pipedream vs n8n Cloud vs self-hosted n8n
| Capability | Pipedream code step | n8n Cloud Code node | Self-hosted n8n Code node |
|---|---|---|---|
| npm packages | Any, installed on deploy | crypto and moment only |
Any installed module listed in NODE_FUNCTION_ALLOW_EXTERNAL |
Node.js built-ins (fs, path) |
Yes | No | If listed in NODE_FUNCTION_ALLOW_BUILTIN |
| Module syntax | import or require |
require only |
require only |
| Python packages | Any PyPI package | None, not even the standard library | If included in the task runner image and allowlisted |
| HTTP requests | Any client | this.helpers.httpRequest or HTTP Request node |
Same, or an allowed npm client |
| Dates | Any library | Luxon DateTime built in, plus moment |
Same, or an allowed library |
| Environment variables | process.env |
$vars on Pro and Enterprise |
$vars on Business and Enterprise, or $env if enabled |
| Connected account tokens | this.app.$auth |
Code nodes can't read credentials | Same |
| Key-value state | Data stores | Static data or Data Tables | Same |
| Files | /tmp and File Stores |
No file system | fs if allowed, or file nodes |
Sources: Code node, enable modules, common issues.
1. HTTP clients: axios, got, node-fetch
n8n exposes this.helpers.httpRequest inside the Code node (options reference). It returns the response body by default, which conveniently matches what @pipedream/platform axios returned on success.
Before, in Pipedream:
import axios from "axios";
export default defineComponent({
async run({ steps, $ }) {
const { data } = await axios.get("https://api.example.com/orders", {
params: { status: "open" },
headers: { Authorization: `Bearer ${process.env.SHOP_TOKEN}` },
});
return data;
},
});
After, in an n8n Code node (mode: Run Once for All Items):
const orders = await this.helpers.httpRequest({
method: "GET",
url: "https://api.example.com/orders",
qs: { status: "open" },
headers: { Authorization: `Bearer ${$vars.SHOP_TOKEN}` },
json: true,
});
// An item's json must be an object, so wrap the array.
return [{ json: { orders } }];
The option names differ from axios: params becomes qs, data becomes body. Set returnFullResponse: true when you need status and headers; you then get { body, headers, statusCode, statusMessage }.
For calls that use a connected account, don't move the token into code at all. n8n Code nodes can't access credentials by design (n8n docs). Put that request in an HTTP Request node, pick the app's predefined credential type, and let n8n handle OAuth refresh. A step that read this.github.$auth.oauth_access_token becomes an HTTP Request node with a GitHub credential.
2. Dates: date-fns, dayjs, moment-timezone
n8n ships Luxon, and its date docs call DateTime the recommended approach. This example comes from Pipedream's own GitHub Sync sample workflow.
Before:
import { parseISO, endOfDay } from "date-fns";
export default defineComponent({
props: { timestamp: { type: "string" } },
async run({ steps, $ }) {
return endOfDay(parseISO(this.timestamp)).toISOString();
},
});
After:
const ts = $input.first().json.timestamp; // e.g. "2026-10-13T09:00:00.000Z"
const end = DateTime.fromISO(ts, { zone: "utc" }).endOf("day");
return [{ json: { endOfDay: end.toISO() } }]; // "2026-10-13T23:59:59.999Z"
date-fns computed endOfDay in the server's local time zone. Pass a zone explicitly in Luxon so the result doesn't depend on the n8n instance's timezone setting.
formatInTimeZone(parseISO(start), tz, "H:mm") from date-fns-tz becomes DateTime.fromISO(start).setZone(tz).toFormat("H:mm"). Plain moment works on n8n Cloud through require("moment"), but moment-timezone does not.
3. steps, $.export and return values
Pipedream passes earlier results in steps. n8n reads earlier nodes with $('node name'), and a Code node must return an array of { json: {...} } items.
Before:
export default defineComponent({
async run({ steps, $ }) {
const { email } = steps.trigger.event.body;
if (!email) return $.flow.exit("no email");
$.export("domain", email.split("@")[1]);
return { email };
},
});
After:
const { email } = $('trigger').first().json.body;
if (!email) return []; // no items: downstream nodes don't run, like $.flow.exit
return [{ json: { domain: email.split("@")[1], $return_value: { email } } }];
Downstream nodes then read {{ $('validate').first().json.domain }} where Pipedream used {{steps.validate.domain}}, assuming the node is named after the Pipedream step. Pipedream code props (this.firstName) have no direct equivalent: inline the values, or read them from an Edit Fields node placed before the Code node.
4. $.respond, delays and suspends
These are workflow-level features in n8n, not code:
$.respond()becomes a Respond to Webhook node, with the Webhook node's Respond option set to "Using 'Respond to Webhook' Node". Have the Code node output the status and body, then reference them in the Respond node. If the workflow finishes without reaching that node, n8n returns a standard 200 message, where Pipedream returned a 400 "No $.respond called in workflow."$.flow.delay(ms)means splitting the step in two with a Wait node (After Time Interval) in between.$.flow.suspend()becomes a Wait node with Resume: On Webhook Call.
5. process.env and secrets
Before: process.env.STRIPE_KEY. After, pick one:
$vars.STRIPE_KEY. n8n Variables are read-only strings (values up to 1,000 characters), set in the UI. Available on n8n Cloud Pro and Enterprise, and self-hosted Business and Enterprise.$env.STRIPE_KEYon self-hosted n8n. Since n8n 2.0,N8N_BLOCK_ENV_ACCESS_IN_NODEdefaults totrue, so this only works if you set it tofalse(n8n 2.0 breaking changes).- A credential on an HTTP Request node. Usually the better home for API keys, and the practical choice on n8n Cloud Starter, which doesn't include Variables.
6. Data stores
A typical counter in Pipedream, using a data store prop:
export default defineComponent({
props: { db: { type: "data_store" } },
async run({ steps, $ }) {
const count = ((await this.db.get("count")) ?? 0) + 1;
await this.db.set("count", count);
return count;
},
});
The same with n8n workflow static data:
const store = $getWorkflowStaticData("global");
store.count = (store.count ?? 0) + 1;
return [{ json: { count: store.count } }];
Know the differences before you rely on it:
- Static data is saved only when a published workflow runs from a trigger or webhook. Manual test runs don't persist it.
- It belongs to one workflow. Pipedream data stores could be shared by many workflows.
- n8n says it "should be small," and there is no TTL like
set(key, value, { ttl }). - It works in JavaScript Code nodes only, not Python.
For shared or larger data, use n8n Data Tables through the Data Table node (Code nodes can't access them directly; default limit 200 MiB per instance), or an external database. Either way, data store records are not in the Pipedream export, so copy them out before April 30, 2027.
7. /tmp and File Stores
Pipedream gave each execution a writable /tmp, and File Stores for longer storage. On n8n Cloud the Code node has no file system access. Pass files between nodes as binary data, use the Convert to File and Extract From File nodes, or store them in S3 or Google Drive. On self-hosted n8n you can allow fs with NODE_FUNCTION_ALLOW_BUILTIN or use the Read/Write Files from Disk node. Download File Store contents from Pipedream before the shutdown, because they are not exported.
8. Python code steps
On n8n Cloud, the Python Code node can't import any library. On self-hosted n8n 2.x, Python runs natively on task runners: imports work only if the n8nio/runners image includes the package and it is allowlisted, the code reads _items or _item instead of pd.steps, and fields use bracket access (item["json"]["email"]). Pyodide-based Python was removed in n8n 2.0. If your Python steps mostly use requests, rewriting them in JavaScript with this.helpers.httpRequest is often faster.
9. Self-hosted: allow your packages
Install the modules into your n8n image, then allow them:
NODE_FUNCTION_ALLOW_BUILTIN=crypto,fs
NODE_FUNCTION_ALLOW_EXTERNAL=date-fns,lodash,stripe
n8n's docs note that if your instance uses task runners, these variables go on the task runners rather than the main n8n process. Convert import statements to require.
How Workflow Exit handles code steps
The free migration report lists every npm package each code step imports and whether n8n Cloud can run it, along with environment variables, data stores, $.flow calls and connected accounts. It runs in your browser.
The paid conversion turns each Node.js step into an n8n Code node with a compatibility layer above your original code. The layer rebuilds steps, $.export, $.flow.exit, this props, data stores (on workflow static data), process.env lookups (a secrets block at the top of the Code node, or n8n Variables on paid plans) and @pipedream/platform axios, axios and node-fetch calls (on this.helpers.httpRequest). It was tested by running converted workflows in n8n 2.x. For packages n8n Cloud can't load, an optional AI rewrite replaces them with n8n built-ins or HTTP calls. Delay blocks become Wait nodes. A $.flow.delay or $.flow.suspend call inside code means the step has to be split around a Wait node, so the report flags those steps and they need a review after conversion. Connected accounts still need n8n credentials, and the generated CHECKLIST.md lists each one.
Plans start at $49 for up to 25 workflows and the first workflow is free (pricing). For the full process, see the Pipedream to n8n migration guide, and for the bigger picture, Pipedream vs n8n. If you haven't exported yet, start with exporting your workflows, then run the report to see how many of your steps hit these limits.
Frequently asked questions
Can I use npm packages in the n8n Cloud Code node?+
No. n8n's Code node documentation says you can't import external npm modules on n8n Cloud. Two modules are available: the crypto Node.js module and the moment package. Self-hosted n8n can allow other installed modules with NODE_FUNCTION_ALLOW_EXTERNAL.
Does axios work in an n8n Code node?+
Not on n8n Cloud, because axios is an external module. Use this.helpers.httpRequest inside the Code node, or an HTTP Request node. On self-hosted n8n you can install axios and add it to NODE_FUNCTION_ALLOW_EXTERNAL.
What replaces process.env from Pipedream in n8n?+
Use n8n Variables ($vars.NAME), available on n8n Cloud Pro and Enterprise and self-hosted Business and Enterprise. On self-hosted n8n you can also use $env.NAME, but since n8n 2.0 Code nodes can only read environment variables if N8N_BLOCK_ENV_ACCESS_IN_NODE is set to false.
What replaces Pipedream data stores in n8n?+
For small per-workflow state, workflow static data via $getWorkflowStaticData('global') in a Code node. For data shared across workflows or larger tables, n8n Data Tables through the Data Table node, or an external database. Static data has no TTL and is only saved on production executions.
Can n8n Cloud run my Pipedream Python code steps?+
Only if they import nothing. On n8n Cloud the Python Code node can't import any library, including the standard library. Rewrite those steps in JavaScript, or self-host n8n and add the packages to the task runner image.
Why does my code say 'import and export may only appear at the top level' in n8n?+
The n8n Code node does not support import or export statements. Pipedream steps use export default defineComponent and import, so remove the wrapper, put the body of run() in the Code node, and load allowed modules with require.