Pipedream sits between Zapier's no-code simplicity and raw Lambda orchestration. It runs workflows on AWS Lambda while exposing Node.js, Python, Go, and Bash code steps inside a visual builder. The platform manages 700+ open-source connectors, each wrapping third-party APIs with authentication, retry logic, and error boundaries. For teams building agentic systems or complex integrations, Pipedream's architecture reveals how to maintain workflow state across serverless invocations, isolate step failures, and handle long-running processes that exceed Lambda's 15-minute timeout.
Execution Model: Step Isolation on Lambda
Pipedream breaks workflows into discrete steps. Each step runs in its own Lambda invocation. The platform serializes state between steps using S3 and DynamoDB, allowing independent retries without re-executing upstream work.
Step lifecycle:
- Trigger fires (HTTP, cron, webhook, event source)
- Platform loads workflow definition and prior state
- Step executes in a Lambda container with language-specific runtime
- Step exports data via
returnor$.export() - Platform persists step output and schedules next step
- On failure, platform retries step with exponential backoff
This model decouples step execution from workflow lifetime. A single workflow can span hours or days because each step is stateless at the Lambda level. The platform handles state persistence, so developers write steps as pure functions that consume inputs and produce outputs.
State Management Across Invocations
Pipedream stores workflow state in two layers:
- Step exports: Immutable outputs from completed steps, stored in S3
-
Workflow state: Mutable key-value store backed by DynamoDB, accessible via
$checkpoint
Step exports flow forward automatically. If step 3 needs data from step 1, the platform injects it into the execution context. Developers reference prior steps with steps.step_name.$return_value.
The $checkpoint API provides mutable state for workflows that need to accumulate data across runs (e.g., deduplication, rate limit tracking). Each workflow instance gets its own checkpoint namespace.
// Step 1: Track seen IDs to deduplicate events
export default defineComponent({
async run({ steps, $ }) {
const seenIds = (await $.checkpoint.get("seen_ids")) || new Set();
const newId = steps.trigger.event.id;
if (seenIds.has(newId)) {
$.flow.exit("Duplicate event");
}
seenIds.add(newId);
await $.checkpoint.set("seen_ids", seenIds);
return { id: newId, isNew: true };
}
});
Checkpoints persist across workflow runs but are scoped to a single workflow instance. They do not share state between different trigger events.
Retry and Error Boundaries
Pipedream enforces retry logic at the step level. Each step gets three automatic retries with exponential backoff (1s, 2s, 4s). Developers can override retry behavior or disable retries entirely.
Error propagation rules:
- Step throws exception → platform retries up to 3 times
- All retries fail → workflow enters error state, downstream steps do not execute
- Step calls
$.flow.exit()→ workflow stops gracefully, no error logged - Step returns falsy value → workflow continues (falsy is valid output)
Connectors (pre-built actions for GitHub, Slack, etc.) inherit platform retry logic but can specify custom backoff strategies. For example, the Slack connector implements rate limit detection and pauses execution until the rate limit window resets.
Developers can add step-level error handlers:
# Step with custom error handling
def handler(pd: "pipedream"):
try:
response = requests.post(pd.steps["trigger"]["event"]["webhook_url"])
response.raise_for_status()
return {"status": "sent"}
except requests.HTTPError as e:
if e.response.status_code == 429:
# Rate limited, exit gracefully and retry later
pd.flow.exit("Rate limited, will retry")
else:
# Log error but continue workflow
print(f"Non-fatal error: {e}")
return {"status": "failed", "error": str(e)}
Connector Architecture: Open-Source Wrappers
Pipedream's 700+ connectors are open-source TypeScript modules. Each connector exposes:
- Auth definitions: OAuth2, API key, or custom credential flows
- Actions: Pre-built functions (e.g., "Send Slack message")
- Triggers: Event sources (e.g., "New GitHub issue")
Connectors live in a public GitHub repository. Developers can fork, modify, or submit new connectors. The platform compiles connectors into Lambda layers at deploy time.
Connector structure:
// Example Slack connector action
import { defineAction } from "@pipedream/types";
import slack from "../../app/slack.app";
export default defineAction({
name: "Send Message",
key: "slack-send-message",
version: "0.0.1",
type: "action",
props: {
slack,
channel: { type: "string", label: "Channel" },
text: { type: "string", label: "Message" }
},
async run({ $ }) {
const response = await this.slack.chat.postMessage({
channel: this.channel,
text: this.text
});
$.export("$summary", `Sent message to ${this.channel}`);
return response;
}
});
The slack prop is an authenticated app instance. Pipedream injects credentials at runtime based on the user's connected account. Connectors never see raw tokens; they call methods on an authenticated client.
Long-Running Workflows and Timeout Handling
Lambda enforces a 15-minute execution limit per invocation. Pipedream handles longer workflows by splitting them into multiple steps. Each step runs in a fresh Lambda invocation, so total workflow duration is unbounded.
For workflows that need to wait (e.g., poll an API every hour for 24 hours), Pipedream provides $.flow.delay():
// Step 1: Start long-running task
export default defineComponent({
async run({ $ }) {
const taskId = await startAsyncTask();
await $.flow.delay(3600 * 1000); // Wait 1 hour
return { taskId };
}
});
// Step 2: Check task status (runs 1 hour later)
export default defineComponent({
async run({ steps, $ }) {
const status = await checkTaskStatus(steps.step1.taskId);
if (status !== "complete") {
await $.flow.delay(3600 * 1000); // Wait another hour
$.flow.rerun(); // Re-execute this step
}
return { status };
}
});
The platform schedules delayed steps using EventBridge. Workflows can delay for up to 1 year.
Code Step Sandboxing and Resource Limits
Code steps run in isolated Lambda containers with language-specific runtimes:
- Node.js: 18.x, 1769 MB memory, 512 MB /tmp
- Python: 3.9, same limits
- Go: 1.x, compiled on-demand
- Bash: Alpine Linux, limited to shell utilities
Each step gets:
- 10-second cold start budget
- 300-second execution limit (5 minutes)
- No outbound network restrictions
- Read-only filesystem except /tmp
Pipedream does not sandbox steps within a single workflow from each other. If step 1 writes to /tmp, step 2 in the same workflow run will not see that file (different Lambda invocations). Steps share data only through explicit exports.
Trade-offs: Pipedream vs. Alternatives
| Dimension | Pipedream | Zapier | Temporal | AWS Step Functions |
|---|---|---|---|---|
| State management | Automatic, S3 + DynamoDB | Opaque | Durable execution history | JSON state machine |
| Code flexibility | Full Node/Python/Go/Bash | Limited code steps | Any language via workers | Lambda or ECS tasks |
| Retry control | Per-step, configurable | Fixed per-plan tier | Developer-defined policies | Configurable per state |
| Connector ecosystem | 700+ open-source | 5000+ closed | Build your own | AWS services only |
| Observability | Built-in logs + metrics | Plan-gated | Self-hosted or Cloud | CloudWatch integration |
| Pricing model | Invocation-based | Task-based | Compute + storage | State transitions |
Pipedream's strength is the hybrid model: visual builder for non-developers, code steps for complex logic, and open connectors for transparency. The platform abstracts Lambda orchestration but does not hide it. Developers can inspect connector source, override retry logic, and debug with full logs.
The weakness is vendor lock-in. Workflows are not portable. Migrating to Temporal or Step Functions requires rewriting orchestration logic. Pipedream's state management is proprietary, so you cannot export workflow state to another system.
Technical Verdict
Use Pipedream when:
- You need rapid integration prototyping with 700+ pre-built connectors
- Your team mixes non-developers (visual builder) and engineers (code steps)
- Workflows require stateful logic (deduplication, rate limiting) but not complex saga patterns
- You want to inspect and modify connector source code
- Execution observability and retry logic must work out of the box
Avoid Pipedream when:
- You need portable workflows that can migrate to other orchestration platforms
- Your workflows require distributed transactions or saga compensation logic
- You need sub-second latency (Lambda cold starts add 1-3 seconds)
- You require on-premises or air-gapped deployment
- Your team already operates Temporal or Step Functions and wants to consolidate tooling
Pipedream is a developer-first Zapier, not a general-purpose orchestration engine. It excels at API glue and event-driven automation. For complex stateful workflows with compensation logic, use Temporal. For AWS-native orchestration, use Step Functions. For everything else, Pipedream's Lambda runtime and open connectors provide a pragmatic middle ground.
Top comments (0)