Pipedream, code first workflows with 3,000 integrations
Pipedream is a workflow platform where a single step is ordinary Node.js, Python, Go, or Bash code, running in the cloud with no server to configure. Every workflow starts with a trigger: an HTTP webhook, a schedule, an inbound email, or an event from one of more than three thousand integrated applications. Billing tracks compute time rather than the number of steps.
How Pipedream differs from the rest of the automation field
Most tools in this category open with the question "what do you want to connect" and hand you a list of boxes to click. Code is permitted as an exception, in a separate node, usually with a restricted runtime and no access to third party packages. Pipedream inverts that order. The primary unit is a code step, and prebuilt actions from the registry are the shortcut you reach for when you cannot be bothered to write yet another Slack API call.
The difference only surfaces around your third or fourth workflow. Box based automation is faster for the first twenty minutes and slower for the rest of the project, because every unusual data transformation has to be worked around. In Pipedream an unusual transformation is three lines of JavaScript, and an unusual integration is a fetch to whatever URL you need.
The second distinguishing feature is less visible from the landing page. Pipedream sells two products under one brand: the public workflow platform, where you build automations for yourself, and Connect, an authentication and integration layer you embed in your own application so that your users link their Gmail or Notion accounts without you writing a single OAuth flow. The second product is what put the company on Workday's radar.
A first workflow in practice
The simplest sensible scenario: accept an HTTP request, validate its contents, write a record, and answer the sender. The HTTP trigger gives you an address you can send anything to.
curl -X POST https://your-endpoint.m.pipedream.net \
-H "Content-Type: application/json" \
-d '{"email":"anna@example.com","plan":"pro"}'The request body lands in steps.trigger.event.body, headers in steps.trigger.event.headers. The next step is code:
export default defineComponent({
async run({ steps, $ }) {
const { email, plan } = steps.trigger.event.body
if (!email || !email.includes("@")) {
$.respond({ status: 400, body: { error: "missing a valid address" } })
return $.flow.exit("rejected at validation")
}
$.export("normalized", { email: email.toLowerCase(), plan: plan ?? "free" })
},
})Two things in that snippet deserve explanation, since both are specific to the platform. $.respond returns a response to the webhook caller, but it only works when the trigger is set to custom response mode. $.flow.exit terminates the entire workflow rather than the current step, so later steps never run and never burn credits.
You have two ways to pass data downstream. A plain return exposes the value as steps.step_name.$return_value, while $.export("normalized", ...) creates a named export available as steps.step_name.normalized. Named exports read better in workflows longer than three steps and should be your default.
npm packages with no package.json
This is a feature that is hard to appreciate until you have spent an afternoon fighting dependencies in another tool. In a Pipedream step you import a package and that is the whole procedure:
import axios from "axios@1.7.7"
import { parse } from "csv-parse/sync"
export default defineComponent({
async run({ steps, $ }) {
const { data } = await axios.get("https://example.com/report.csv")
return parse(data, { columns: true })
},
})There is no manifest file, no install step, no cache to clear. The name@version syntax pins a specific release, and it is worth using anywhere a workflow should behave the same six months from now. An unpinned import takes the latest available version, which is a quiet time bomb for packages that change their API across major releases. The workflow runs for months, then starts throwing TypeError at three in the morning because a library author changed a function signature.
Python behaves the same way, with imports resolved automatically, and earns its place mainly where you need a library with no reasonable JavaScript counterpart. For tabular data work or machine learning models it is often the only sane choice.
Credits, or what you actually pay for
The billing model differs from the competition, and it decides whether the invoice surprises you. You do not pay per task or per step in a workflow. You pay for compute time multiplied by allocated memory.
The unit is a credit: thirty seconds of execution at the default 256 MB of memory. Doubling memory doubles the credit burn rate. A step configured at 1 GB consumes credits four times faster than the same step on defaults, at identical runtime.
That yields the first practical piece of advice, one that saves money in a way the invoice never shows: do not raise memory as a precaution. The memory slider is tempting, because CPU allocation rises with it and the workflow genuinely finishes sooner. The bill rarely benefits, though, since a twofold speedup at a fourfold unit cost is a losing trade. Raise memory only when a step genuinely handles large in memory structures and falls over otherwise.
The second piece of advice concerns workflow structure. Since time counts and step count does not, splitting logic into many small readable steps costs nothing. That is a rare situation in this category, where each extra node usually carries a charge. Here readability is free, so use it.
Limits worth knowing before you design
| Limit | Value |
|---|---|
| Default timeout, HTTP and email triggers | 30 seconds |
| Default timeout, schedule trigger | 60 seconds |
| Maximum timeout, free plan | 300 seconds |
| Maximum timeout, paid plans | 750 seconds |
| Default and maximum memory | 256 MB, up to 10 GB |
| HTTP request body | 512 KB |
| Email including attachments | 30 MB |
| Logs, step exports, and event data combined | 6 MB |
Disk space in /tmp | 2 GB |
| Requests to an endpoint | 10 per second on average, with burst tolerance |
| Event history, free plan | 7 days |
The 512 KB body limit is where most first deployments break. You cannot post a file through a webhook and process it in a step. The fix is to send the file's address instead and download it inside the workflow into /tmp, where 2 GB is available. That same pattern, passing a pointer rather than contents, applies to every platform in this class and recurs in Kestra and Prefect.
The 6 MB combined limit on logs and exports is sneakier still, because it only appears in production. A step that returned twenty records in testing returns twenty thousand in production, and the whole workflow dies trying to persist the export. If a step pulls paginated data, process it in a loop and export a summary rather than the raw response.
Connect, authentication as a product
If you build an application where users link their own accounts in third party services, you know how much work goes into writing and maintaining a dozen OAuth flows. Token refresh, revoked consent, implementation differences between providers, secret storage. Connect moves all of that to Pipedream's side and exposes an interface where you request a user's account and receive either working credentials or an authorization link.
In practice your application mints a token scoped to a specific user, who then walks a short authorization path in a browser window. Your backend never sees a password and never stores a refresh token.
const response = await fetch("https://api.pipedream.com/v1/connect/tokens", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
external_user_id: user.id,
allowed_origins: ["https://your-application.com"],
}),
})The external_user_id field deserves attention. It is your user identifier, not one from Pipedream's system, and it binds connected accounts to a person in your database. Choosing something mutable here, an email address rather than a primary key for instance, loses those bindings the first time a user changes their address.
The MCP server and agents
Model Context Protocol changed how tools reach language models, and Pipedream exposes its integrations in exactly that shape. The remote server runs at https://remote.mcp.pipedream.net/v3 and supports both SSE and streamable HTTP, picking the transport on its own.
Scale is the main argument here: more than three thousand APIs and over ten thousand tools available without you writing a single wrapper. A request is routed by headers naming the project, environment, user, and target application:
curl https://remote.mcp.pipedream.net/v3 \
-H "Authorization: Bearer $TOKEN" \
-H "x-pd-project-id: proj_abc123" \
-H "x-pd-environment: production" \
-H "x-pd-external-user-id: user_42" \
-H "x-pd-app-slug: linear"The missing account mechanism is the interesting part. When a user has not connected Linear yet, the server does not return an error but a Connect Link URL you can show them. The agent does not stall on a missing permission, it receives an exit path. That small design decision saves a fair amount of code in the agent layer and reads better than most of what I have seen across the MCP server registry.
Developer side authentication runs through OAuth client credentials, with a token fetched from https://api.pipedream.com/v1/oauth/token. The token has a limited lifetime, so production code needs a refresh layer rather than a fixed value in an environment variable.
Pipedream against the alternatives
| Feature | Pipedream | n8n | Zapier | Make |
|---|---|---|---|---|
| Primary unit | code step | visual node | action from a list | module on a scenario |
| Billing | compute time and memory | tasks or self hosting | tasks | operations |
| Self hosting | no | yes, fair code licence | no | no |
| Third party packages | anything on npm and PyPI | limited in cloud | none | none |
| Built in layer for end users | yes, Connect | no | partial | no |
| Entry barrier for a non developer | high | medium | low | medium |
The choice between these four is rarely about features, since most routine tasks are within reach of all of them. The real criterion is who maintains these workflows over the next year. If that is a non technical team, Pipedream is the wrong pick and there is no point pretending otherwise: the interface assumes you can read code, and its errors are runtime errors rather than friendly hints.
If a developer writes the workflows, the situation reverses. Boxes start getting in the way, and the option to write four lines instead of hunting for the right node saves more time than intuition suggests. A separate case is a requirement to keep data in house. Pipedream has no self installed edition, and in projects with hard data residency requirements that closes the discussion.
The Workday acquisition and what is known
On 19 November 2025 Workday announced a definitive agreement to acquire Pipedream, and the transaction closed in December of the same year, ahead of the original schedule. The buyer's rationale is agent integrations: Workday wants its agents reaching into external systems, and Pipedream already has the connections.
Pipedream's own post was brief and contained no product commitments. Not a word about the fate of the free plan, about pricing, or about whether the public workflow platform stays a priority alongside the embedded Connect layer. More than six months have passed since the close and those commitments have still not appeared, so on a commercial product built on this platform it pays to keep a fallback plan and to watch the vendor's announcements rather than assume continuity.
Treat that as planning risk rather than a reason to walk away. Workflows in Pipedream are ordinary Node.js or Python code, so relocating the logic elsewhere is feasible, unlike platforms where the whole value sits in a clicked graph. The layer that is hard to replicate is Connect and the integration catalogue, and that is where a contingency plan is worth having if you build a commercial product on it.
Pricing and what cannot be confirmed today
Pipedream offers a free plan with a daily credit cap, a limited number of active workflows and connected accounts, and paid plans that raise the execution timeout to 750 seconds and extend event history retention. The documentation describes the mechanics of those limits in detail but does not state amounts.
Specific plan prices are deliberately absent here. Third party sources that quote them disagree with each other on both the monthly amounts and the size of the free credit allowance, and the official pricing page renders in the browser and cannot be quoted reliably. Publishing an unverifiable number would be worse than publishing none, particularly in a text somebody returns to six months later.
Work it out yourself instead, since with a compute based model that is the only meaningful method. Run the target workflow ten times against real data, read the execution time, multiply by expected daily volume, and divide by thirty seconds. That gives you daily credit consumption to compare against the pricing page on the day you decide.
Common mistakes and limitations
The first is skipping retry safety in your own logic. A workflow that inserts a record will insert it twice on retry unless you supply an idempotency key. Automatic retries are a platform feature, while the safety of those retries is your responsibility.
The second is holding state between runs in variables. Every execution starts fresh, so a counter incremented in a global variable does not survive. Durable state belongs in the data store or an external database such as Redis.
The third is an overly optimistic view of the default thirty second timeout. A language model call with a longer context regularly exceeds it, and the resulting error looks like an API problem when it is simply a timeout. When working with models, raise the limit and stream the response where the target platform allows it.
The fourth concerns testing. Test runs do not consume credits, which is convenient but breeds the illusion that a workflow is cheap. The cost only appears after you switch it on in production and get through a first day of real traffic.
The fifth is relying on unpinned versions. I mentioned this earlier under imports and return to it because it is the most common cause of failures in workflows that ran untouched for months.
Wiring it into a Next.js stack
A typical arrangement in a Next.js project has the application expose an API route that forwards the event to Pipedream, with long running work happening outside the request cycle. The user gets an immediate response and processing takes however long it takes.
export async function POST(request: Request) {
const payload = await request.json()
await fetch(process.env.PIPEDREAM_ENDPOINT!, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-signature": sign(payload),
},
body: JSON.stringify(payload),
})
return Response.json({ accepted: true }, { status: 202 })
}The signature header is not decoration. An HTTP trigger address is public, and anyone who learns it can post arbitrary data to it. The first step of the workflow should verify the signature and exit on mismatch, before anything reaches a database. Types shared between the application and the workflow steps are worth keeping in one place and exporting as a package, which in a TypeScript project costs a quarter of an hour and prevents an entire class of bugs caused by data shapes drifting apart.
FAQ
Can Pipedream run on my own server?
No. Pipedream operates purely as a cloud service with no official self installed edition. If project requirements force data onto your own infrastructure, n8n is the sensible alternative, with its fair code licence and a self hosted variant.
What does a single workflow run cost?
Cost is counted in credits, where one credit is thirty seconds of execution at 256 MB of memory. A workflow finishing in five seconds on defaults consumes a fraction of a credit, and the same workflow at 1 GB consumes four times as much. Step count has no effect on the bill.
How does Connect differ from ordinary workflows?
Ordinary workflows are built for yourself, with your own accounts connected inside them. Connect exists so your users can link their accounts from within your application, without you implementing OAuth flows for each provider separately. They are two distinct products sharing one integration catalogue.
Can I use any npm package?
Yes, import it in a step, with no manifest file and no install. Pin the version with the package@version syntax, because an unpinned import pulls the latest release and a workflow can break after a library's major version bump.
What happens to Pipedream after the Workday acquisition?
Workday signed the acquisition agreement on 19 November 2025 and the transaction closed in December of the same year. Pipedream announced no changes to the product, pricing, or free plan at the time and has not done so in the months since. Until official statements appear, treat the public platform's future as uncertain and keep a contingency plan for any commercial product built on it.
Limit details and step syntax are covered in the Pipedream documentation, and the acquisition announcement is on the Workday newsroom.