ActivePieces: An open-source automation platform (MIT, 12k stars)
An open-source automation platform with AI-powered workflow builder, pieces framework, and self-hosted deployment for enterprise automation.
The Problem
Every SaaS team hits the same wall: the tools don’t talk to each other. Slack doesn’t know about Salesforce. GitHub doesn’t trigger Jira. Stripe doesn’t update Google Sheets. The standard solution is Zapier or Make — but those come with per-task pricing that scales linearly with your business. A team processing 100,000 automated tasks per month on Zapier pays $599/month. At 1 million tasks, that’s $2,999/month. The cost grows with success.
The alternatives are not much better. n8n is open-source but uses a Sustainable Use License (not MIT) that explicitly prohibits reselling the tool itself — a dealbreaker for SaaS companies that want to embed automation into their product. Huginn is MIT-licensed but has a Ruby codebase that most modern teams don’t want to maintain, a dated UI, and no AI capabilities.
| Dimension | Zapier | Make | n8n | ActivePieces |
|---|---|---|---|---|
| License | Proprietary | Proprietary | Sustainable Use (Fair Code) | MIT |
| Self-hosted | No ($299/mo enterprise) | No | Yes (free) | Yes (free) |
| AI agents | Yes (limited) | No | Yes (LangChain) | Yes (native) |
| MCP support | No | No | No | Yes (280+ MCP servers) |
| Custom integrations | Limited (webhooks) | Limited (webhooks) | JS/Python code nodes | TypeScript pieces framework |
| Embeddable | No | No | No | Yes (embed SDK) |
| White-label | No | No | No | Yes (custom domain, logo, CSS) |
| Per-task pricing | Yes ($0.05/100 tasks) | Yes (ops-based) | No (self-hosted) | No (self-hosted) |
| GitHub stars | N/A | N/A | 186,000 | 22,934 |
| Integrations | 6,000+ | 1,500+ | 500+ | 600+ |
Why this matters: The automation market has a gap between “easy but expensive” (Zapier) and “powerful but restrictive” (n8n). ActivePieces fills that gap with an MIT license that lets you self-host, embed, white-label, and resell — all without per-task costs. The tradeoff is a smaller integration catalog and a younger ecosystem. For teams that value licensing freedom over catalog depth, this is the only option that checks every box.
The Investigation
ActivePieces started in 2023 as a direct response to the Zapier pricing problem. The founders, led by Mohammad AbuAboud, had built automation platforms before and knew the space intimately. Their investigation surfaced three structural problems with existing solutions.
Finding 1: Per-task pricing is a tax on success.
Every automation platform that charges per execution creates a perverse incentive: the more value you get from automation, the more you pay. A company running 500,000 automated tasks per month on Zapier pays $1,499/month. At 2 million tasks, that’s $5,999/month. The cost scales with the value the platform delivers, not with the cost of running it.
ActivePieces’ investigation found that the actual infrastructure cost of running an automation task is approximately $0.000001 — roughly 1/50,000th of what Zapier charges. The markup is not about infrastructure; it’s about margin. Self-hosting eliminates this entirely.
Finding 2: Non-MIT licenses create adoption barriers.
n8n’s Sustainable Use License prohibits selling the software itself. This means:
- A SaaS company cannot embed n8n as their product’s automation engine
- A consultancy cannot resell n8n as part of a managed automation service
- An enterprise cannot fork and customize the codebase for internal use without legal review
ActivePieces’ investigation concluded that MIT licensing was non-negotiable for enterprise adoption. Every legal team they spoke to flagged the n8n license as a risk. The MIT license has no such ambiguity — you can use it, modify it, embed it, and resell it without restriction.
Finding 3: The integration model determines the ecosystem’s growth rate.
Zapier’s 6,000+ integrations are built by Zapier’s own team. This is a bottleneck — Zapier decides what to build, not the community. n8n’s 500+ integrations are community-contributed, but the node-based architecture makes each integration a complex, multi-file TypeScript project.
ActivePieces designed a pieces framework that treats every integration as a single TypeScript file with a standardized interface. The result: 60% of ActivePieces’ 600+ integrations are community-contributed, and the framework is published on npm so anyone can build and publish a piece without touching the core repository.
| Integration Model | Zapier | n8n | ActivePieces |
|---|---|---|---|
| Built by | Vendor team | Community + vendor | Community + vendor |
| Integration format | Proprietary | Node (multi-file) | Piece (single-file TypeScript) |
| Published on | Zapier’s platform | GitHub PR | npm + GitHub |
| Community share | ~0% | ~40% | ~60% |
| Time to add new integration | Weeks (vendor queue) | Days (PR review) | Hours (npm publish) |
The Solution
ActivePieces is a ~200,000-line TypeScript monorepo (MIT license, 22,934 GitHub stars, 360+ contributors) that provides a visual workflow builder, a pieces framework for integrations, and a self-hosted deployment model. It runs on Node.js with PostgreSQL and Redis, and every piece you build automatically becomes an MCP server for use with Claude Desktop, Cursor, and Windsurf.
┌──────────────────────────────────────────────────────────────────────────┐
│ ActivePieces Architecture │
│ │
│ ┌──────────────┐ ┌──────────────────┐ ┌───────────────────────┐ │
│ │ React UI │ │ API Server │ │ Worker Pool │ │
│ │ (Flow │───▶│ (Fastify) │───▶│ (BullMQ + Redis) │ │
│ │ Builder) │ │ │ │ │ │
│ │ │ │ • Auth/RBAC │ │ • Flow execution │ │
│ │ • Drag-drop │ │ • Flow CRUD │ │ • Sandboxed engine │ │
│ │ • Step panel │ │ • Webhooks │ │ • Retry/backoff │ │
│ │ • Live debug │ │ • Scheduled jobs│ │ • Telemetry │ │
│ └──────────────┘ └────────┬─────────┘ └───────────┬───────────┘ │
│ │ │ │
│ ┌──────────┴──────────┐ ┌──────────┴──────────┐ │
│ │ PostgreSQL │ │ Engine Runtime │ │
│ │ (flows, users, │ │ (isolated-vm or │ │
│ │ executions) │ │ child_process) │ │
│ └─────────────────────┘ └──────────┬──────────┘ │
│ │ │
│ ┌─────────────────────────────────────┴──────────┐ │
│ │ Pieces Framework (npm) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │
│ │ │ Core │ │ Community│ │ Custom │ │ │
│ │ │ (HTTP, │ │ (600+ │ │ (your own │ │ │
│ │ │ CSV, │ │ pieces) │ │ pieces) │ │ │
│ │ │ Forms) │ │ │ │ │ │ │
│ │ └──────────┘ └──────────┘ └──────────────┘ │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ MCP Server (auto-generated from pieces) │ │
│ │ Claude Desktop ←→ Cursor ←→ Windsurf ←→ Any MCP client │ │
│ └──────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘
Here is what each component does:
-
React UI: A drag-and-drop flow builder built in React. Users compose workflows by selecting triggers and actions from a step panel. Each step is a piece action or trigger with typed inputs. The UI supports loops, conditional branches, approval steps, and human-in-the-loop forms.
-
API Server (Fastify): The backend API that manages authentication, flow CRUD, webhook registration, scheduled job management, and user administration. It uses Fastify for HTTP, BullMQ for job queues, and PostgreSQL for persistence.
-
Worker Pool: Background workers that poll Redis for new jobs and execute flows. Workers are horizontally scalable — add more workers to increase throughput. Each worker runs the engine in a sandboxed environment.
-
Engine Runtime: The core execution engine that parses flow JSON and runs each step. Supports four sandboxing modes:
UNSANDBOXED(fastest, least secure),SANDBOX_CODE_ONLY(V8 isolation viaisolated-vm),SANDBOX_PROCESS(Linux namespace isolation), andSANDBOX_CODE_AND_PROCESS(both). The unsandboxed mode is 50x faster than sandboxed and suitable for single-tenant deployments. -
Pieces Framework: The integration framework published as
@activepieces/pieces-frameworkon npm. Each piece is a TypeScript module with actions and triggers. Pieces are auto-discovered and hot-reloaded during development. -
MCP Server: Every piece in the ActivePieces ecosystem is automatically available as an MCP server. Connect Claude Desktop, Cursor, or Windsurf to your ActivePieces instance and build flows through natural language.
Setup
# Production deployment with Docker Compose
mkdir activepieces && cd activepieces
wget https://raw.githubusercontent.com/activepieces/activepieces/main/docker-compose.yml
# Generate required secrets
export AP_ENCRYPTION_KEY=$(openssl rand -hex 16)
export AP_JWT_SECRET=$(openssl rand -hex 32)
# Edit docker-compose.yml with your secrets and domain
# Then start
docker compose up -d
# Open http://localhost:8080
# Create your admin account
# Disable public signups:
# docker compose exec activepieces \
# ap-flags --set SIGN_UP_ENABLED false
Production-Grade Configuration
# docker-compose.yml — production configuration
version: "3.8"
services:
activepieces:
image: activepieces/activepieces:latest
restart: unless-stopped
ports:
- "8080:80"
environment:
AP_POSTGRES_DATABASE: activepieces
AP_POSTGRES_HOST: postgres
AP_POSTGRES_PORT: 5432
AP_POSTGRES_USERNAME: postgres
AP_POSTGRES_PASSWORD: "${AP_POSTGRES_PASSWORD}"
AP_REDIS_HOST: redis
AP_REDIS_PORT: 6379
AP_ENCRYPTION_KEY: "${AP_ENCRYPTION_KEY}"
AP_JWT_SECRET: "${AP_JWT_SECRET}"
AP_FRONTEND_URL: "https://automation.example.com"
AP_SIGN_UP_ENABLED: "false"
AP_EXECUTION_MODE: "UNSANDBOXED" # 50x faster for single-tenant
AP_TELEMETRY_DISABLED: "true"
AP_MAX_CONCURRENT_JOBS: "50"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- activepieces_data:/app/data
postgres:
image: postgres:15
restart: unless-stopped
environment:
POSTGRES_DB: activepieces
POSTGRES_USER: postgres
POSTGRES_PASSWORD: "${AP_POSTGRES_PASSWORD}"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 5
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
activepieces_data:
Code Walkthrough: Building a Custom Piece
The pieces framework is the heart of ActivePieces’ extensibility. Here is a complete custom piece that integrates with a fictional API:
// packages/pieces/community/my-service/src/index.ts
import {
createPiece,
PieceAuth,
Property,
createAction,
createTrigger,
TriggerStrategy,
} from '@activepieces/pieces-framework';
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
import { PieceCategory } from '@activepieces/shared';
// 1. Define authentication
export const myServiceAuth = PieceAuth.SecretText({
displayName: 'API Key',
description: 'Your MyService API key',
required: true,
});
// 2. Define an action
export const createRecord = createAction({
name: 'create_record',
displayName: 'Create Record',
description: 'Creates a new record in MyService',
auth: myServiceAuth,
props: {
title: Property.ShortText({
displayName: 'Title',
description: 'The record title',
required: true,
}),
description: Property.LongText({
displayName: 'Description',
description: 'The record description',
required: false,
}),
priority: Property.Dropdown({
displayName: 'Priority',
description: 'Record priority level',
required: true,
refreshers: [],
options: async () => ({
options: [
{ label: 'Low', value: 'low' },
{ label: 'Medium', value: 'medium' },
{ label: 'High', value: 'high' },
{ label: 'Critical', value: 'critical' },
],
}),
}),
},
async run(context) {
const { auth, propsValue } = context;
const response = await httpClient.sendRequest({
method: HttpMethod.POST,
url: 'https://api.myservice.com/v1/records',
headers: {
Authorization: `Bearer ${auth.secret_text}`,
'Content-Type': 'application/json',
},
body: {
title: propsValue.title,
description: propsValue.description,
priority: propsValue.priority,
},
});
return response.body;
},
});
// 3. Define a webhook trigger
export const newRecord = createTrigger({
name: 'new_record',
displayName: 'New Record',
description: 'Triggers when a new record is created',
auth: myServiceAuth,
props: {},
sampleData: {
id: 'rec_123',
title: 'Sample Record',
priority: 'medium',
created_at: '2026-06-23T12:00:00Z',
},
type: TriggerStrategy.WEBHOOK,
async onEnable(context) {
const webhookUrl = context.webhookUrl;
await httpClient.sendRequest({
method: HttpMethod.POST,
url: 'https://api.myservice.com/v1/webhooks',
headers: {
Authorization: `Bearer ${auth.secret_text}`,
},
body: { url: webhookUrl, events: ['record.created'] },
});
},
async run(context) {
return [context.payload.body];
},
async onDisable(context) {
// Unregister webhook on flow disable
},
});
// 4. Register the piece
export const myService = createPiece({
displayName: 'MyService',
description: 'Integration with MyService API',
auth: myServiceAuth,
minimumSupportedRelease: '0.30.0',
logoUrl: 'https://cdn.activepieces.com/pieces/my-service.png',
categories: [PieceCategory.PRODUCTIVITY],
authors: ['your-github-username'],
actions: [createRecord],
triggers: [newRecord],
});
The piece is published to npm and auto-discovered by ActivePieces. No changes to the core repository are needed. The same piece is also available as an MCP server — Claude Desktop can call create_record and new_record through the MCP protocol without any additional configuration.
How to Use Effectively
Step 1: Deploy and configure
# Deploy with Docker Compose (see Setup section)
docker compose up -d
# Open the UI at http://localhost:8080
# Create your admin account
# Navigate to Settings > MCP Server and enable it
# Copy the MCP Server URL
# Configure Claude Desktop
cat >> ~/Library/Application\ Support/Claude/claude_desktop_config.json << 'EOF'
{
"mcpServers": {
"activepieces": {
"url": "https://automation.example.com/mcp"
}
}
}
EOF
Step 2: Build your first flow
Open the ActivePieces UI and create a new flow. The builder presents a vertical step list — each step is a trigger or action from a piece. Start with a trigger (e.g., “New Row in Google Sheets”), add actions (e.g., “Send Slack Message”, “Create Jira Issue”), and connect them.
The flow builder supports:
- Loops: Iterate over arrays from previous steps
- Branches: Conditional logic with if/else paths
- Approval steps: Pause execution until a human approves
- Code steps: Write JavaScript/TypeScript with full npm access
- Error handling: Configure retries with exponential backoff
Step 3: Use MCP for natural language flow building
# In Claude Desktop, after connecting to ActivePieces MCP:
"Create a flow that watches a Google Sheet for new rows.
When a new row appears, check if the priority column is 'High'.
If it is, create a Jira ticket and send a Slack notification to the #ops channel."
# Claude will:
# 1. Create the flow in ActivePieces
# 2. Add the Google Sheets trigger (new row)
# 3. Add a branch condition on priority
# 4. Add Jira create-ticket action (high priority branch)
# 5. Add Slack send-message action (high priority branch)
# 6. Publish and enable the flow
Production pitfall: MCP-based flow building is powerful but imprecise for complex logic. Use it for rapid prototyping and simple flows. For production workflows with multiple branches, error handling, and data transformations, build in the visual editor where you can see every step and test each one individually.
Step 4: Test and debug
# Each flow step can be tested individually
# Click the "Test" button on any step to run it with sample data
# View execution logs in the Runs tab
# Failed steps show the exact error and payload
# For code steps, add logging:
console.log('Processing record:', JSON.stringify(record));
# Logs appear in the execution run details
Step 5: Version control with Git Sync
# In Settings > Git Sync, connect a GitHub/GitLab repository
# Flow versions are pushed as JSON files
# Each flow gets its own directory with versioned files
# Workflow:
# 1. Edit flow in ActivePieces UI
# 2. Save as draft (versioned locally)
# 3. Push to Git repo
# 4. Pull on another instance (dev → staging → production)
# 5. Lock the flow in production to prevent accidental edits
Use Cases
1. Customer Onboarding Automation
When you’d use this: A SaaS company needs to automate the new customer onboarding flow — create account in Stripe, provision a workspace, send welcome email, add to CRM, schedule onboarding call.
Why ActivePieces fits: The MIT license means you can embed ActivePieces directly into your SaaS product. New customers trigger a flow that provisions their account across all your tools. The approval step lets your team review high-value accounts before provisioning. Self-hosting keeps customer data on your infrastructure.
2. Internal Operations Hub
When you’d use this: A mid-size company (50-200 employees) wants to connect Slack, Google Workspace, Jira, GitHub, and their internal tools without per-task costs.
Why ActivePieces fits: Self-hosting on a single VM costs ~$20/month in infrastructure. There are no per-task fees. A team running 50,000 automated tasks per month pays $20 instead of $599 (Zapier). The white-label feature lets you brand the automation portal with your company logo and domain.
3. AI Agent Workflows with MCP
When you’d use this: A team wants Claude Desktop to be able to read from their database, write to their CRM, send Slack messages, and create Jira tickets — all through natural language.
Why ActivePieces fits: Every piece in ActivePieces is automatically an MCP server. Connect Claude Desktop to your ActivePieces instance, and Claude can call any of your 600+ integrations through the MCP protocol. This is the largest open-source MCP toolkit available — 280+ MCP servers out of the box.
4. Embedded Automation Platform
When you’d use this: A SaaS company wants to offer workflow automation as a feature of their product — letting customers build custom automations between their product and external tools.
Why ActivePieces fits: The embed SDK lets you embed the flow builder inside your own React application. The MIT license means you can resell ActivePieces as part of your product without licensing fees. White-label branding makes it look like your own product. This is the use case that no other open-source automation tool supports.
5. Compliance-Gated Workflows
When you’d use this: A regulated industry (healthcare, finance, government) needs automated workflows that never touch third-party infrastructure.
Why ActivePieces fits: Self-hosted on your own infrastructure with network-gapped deployment. No data leaves your VPC. Sandboxed execution prevents flow code from accessing the host system. Audit logs track every execution. SSO and RBAC control who can create, edit, and enable flows.
Cheat Sheet
| Aspect | Detail |
|---|---|
| Repository | github.com/activepieces/activepieces |
| License | MIT (Community Edition) |
| Language | TypeScript (~200,000 lines, monorepo with NX) |
| Dependencies | PostgreSQL 14+, Redis 7.0+, Node.js 20+ |
| Setup Time | 5 minutes (Docker Compose) |
| Key Features | Visual flow builder, 600+ pieces, MCP server, AI agents, human-in-the-loop, embed SDK, white-label, Git sync, RBAC, audit logs |
| Common Gotchas | Forgetting to set AP_ENCRYPTION_KEY (32 hex chars); running sandboxed in single-tenant (use UNSANDBOXED for 50x speed); not disabling signups after admin creation; missing Redis in production |
| Best For | Self-hosted automation, embedded workflows, AI agent toolkits, compliance-gated automation |
| Cost (Self-hosted) | ~$20-50/month (VM + DB) |
| Cost (Cloud Free) | 1,000 tasks/month |
| Cost (Cloud Pro) | $10/month (unlimited tasks) |
| Missing Features | Smaller integration catalog than Zapier (600 vs 6,000); no Python code steps; no native sub-workflow support; younger community than n8n |
Vibe Coding Projects
Project 1: Slack-to-Jira Issue Creator
What it does: A flow that watches a Slack channel for messages containing specific keywords (e.g., “bug:”, “feature:”, “urgent:”). When a matching message appears, it creates a Jira issue with the message content, links back to the Slack thread, and posts a confirmation in the channel. Includes an approval step for “urgent” issues — a manager must approve before the ticket is created.
What you’ll learn: How to set up webhook triggers, use conditional branching, implement human-in-the-loop approval steps, and chain multiple actions across different pieces. You’ll also learn how to test each step individually and debug failed executions.
Effort: 1-2 hours. No API costs (self-hosted).
Project 2: Multi-Platform Content Syndicator
What it does: A flow that watches a Google Sheet for new rows containing blog post metadata (title, content, tags, publish date). When a new row appears, it publishes the post to WordPress, creates a LinkedIn article, posts to Twitter/X, sends a newsletter via Mailchimp, and logs the results back to the Google Sheet. Includes error handling — if one platform fails, the others still proceed.
What you’ll learn: How to build multi-branch flows with error handling, use code steps for data transformation (converting markdown to platform-specific formats), and implement retry logic for transient failures. You’ll also learn how to use the data-mapper piece to reshape payloads between steps.
Effort: 2-3 hours. ~$10/month in API costs for Mailchimp/LinkedIn.
Project 3: Custom AI Research Agent with MCP
What it does: A flow that connects Claude Desktop (via MCP) to a research pipeline. When a user asks a research question in Claude, the flow: (1) searches the web via a search API piece, (2) scrapes the top results via the HTTP piece, (3) summarizes each result using the AI piece (OpenAI/Anthropic), (4) stores the results in a PostgreSQL table, and (5) returns a formatted research brief to Claude.
What you’ll learn: How to build flows that combine MCP-driven AI agents with traditional automation pieces. How to use the AI piece for text processing within a flow. How to store and retrieve data from tables. How to build a feedback loop where Claude can trigger follow-up research based on initial results.
Effort: 3-4 hours. ~$5-10 in API costs (LLM tokens + search API).
Problems Solved Efficiently
| Problem Type | Why ActivePieces Fits | When to Look Elsewhere |
|---|---|---|
| Per-task cost avoidance | Self-hosted MIT license, no per-execution fees | Use Zapier for zero-infrastructure setup |
| Embedding automation in SaaS | Embed SDK + MIT license for resale | Use n8n for complex enterprise workflows |
| AI agent tool integration | 280+ MCP servers, native AI pieces | Use LangChain for custom AI agent frameworks |
| Compliance-gated automation | Self-hosted, network-gapped, sandboxed execution | Use Zapier Enterprise for managed compliance |
| White-label automation portal | Custom domain, logo, CSS theming | Use Make for no-code team adoption |
| Simple internal automations | 5-minute Docker setup, clean UI | Use n8n for complex branching and sub-workflows |
| Community-driven integrations | npm-based pieces framework, 60% community | Use Zapier for 6,000+ pre-built integrations |
| Multi-tenant automation platform | RBAC, project isolation, audit logs | Build custom with Temporal for full control |
Architectural Tradeoffs
What we gained:
- MIT licensing freedom. No restrictions on embedding, reselling, forking, or modifying. This is the only major open-source automation platform with a true MIT license. Every legal team approves it without review.
- MCP-native architecture. Every piece is automatically an MCP server. This is a first-mover advantage — no other automation platform has this. It makes ActivePieces the largest open-source MCP toolkit by a wide margin.
- TypeScript-first extensibility. The pieces framework is published on npm. Anyone can build, test, and publish a piece without touching the core repository. Hot reloading means you see changes instantly during development.
- Clean, modern UI. The step-based vertical builder is more intuitive than n8n’s node-based canvas. Non-technical users can build flows without training. G2 rates ActivePieces 9.1/10 for ease of use (vs. n8n’s 7.9/10).
- Predictable infrastructure costs. Self-hosting on a $20/month VM handles unlimited tasks. No surprise bills at the end of the month.
What we sacrificed:
- Smaller integration catalog. 600+ pieces vs. Zapier’s 6,000+ and n8n’s 1,000+. For obscure or legacy tools, you may need to build your own piece. The pieces framework makes this straightforward, but it’s still work.
- Lower throughput. ActivePieces processes each task in an isolated process (for security), which adds ~15 seconds of overhead per task vs. n8n’s ~1 second. The unsandboxed mode closes this gap (50x faster) but reduces security isolation.
- Younger ecosystem. 22,934 GitHub stars vs. n8n’s 186,000. Fewer community resources, fewer tutorials, fewer third-party tools. The community is growing fast but is not yet at n8n’s scale.
- No Python code steps. Code steps are JavaScript/TypeScript only. Teams that prefer Python for data processing must use the HTTP piece to call an external Python service.
- No native sub-workflows. n8n supports sub-workflows (calling one workflow from another). ActivePieces requires you to duplicate logic or use webhooks for cross-flow communication.
- Process-per-task overhead. Each execution spawns a new process, which increases latency and memory usage. n8n’s shared-worker model is more efficient for high-throughput scenarios.
The real lesson: ActivePieces is not a drop-in replacement for Zapier or n8n. It is a different category of tool — one optimized for licensing freedom, AI integration, and embeddability. If you need 6,000 integrations and don’t care about MIT licensing, use Zapier. If you need high-throughput enterprise automation with sub-workflows, use n8n. If you need to embed automation into your product, white-label it, connect it to AI agents via MCP, and never pay per task — use ActivePieces.
Course-Style Deep Dive
How the Pieces Framework Works Under the Hood
The pieces framework is the architectural foundation of ActivePieces. Here is how it works, step by step:
-
Piece Registration. Each piece is an npm package that exports a
createPiece()call. The package is published to npm and installed by the ActivePieces server. The server discovers installed pieces at startup by scanningnode_modulesfor packages matching the@activepieces/piece-*pattern. -
Schema Generation. When a piece is loaded, ActivePieces introspects its actions and triggers to generate a JSON schema. Each action’s
propsare converted to a JSON Schema definition that the UI renders as form fields. The schema includes validation rules (required fields, types, dropdown options) that are enforced at both the UI level and the engine level. -
Action Execution. When a flow reaches an action step, the engine:
- Loads the piece’s compiled JavaScript
- Validates the input against the action’s schema
- Calls the action’s
run()function with the validated context - Captures the return value and passes it to the next step
- Logs execution metrics (duration, input size, output size)
-
Trigger Polling. For polling triggers, the engine calls
run()on a schedule (configurable per trigger, default 5 minutes). The trigger returns an array of new events. Each event becomes a separate flow execution. The trigger’sstoreAPI tracks state between polls (e.g., last poll timestamp). -
Webhook Registration. For webhook triggers, the engine calls
onEnable()when a flow is enabled. The trigger registers a webhook URL with the external service. When the webhook fires, ActivePieces matches the incoming request to the correct flow and starts execution. TheonDisable()callback unregisters the webhook when the flow is disabled. -
MCP Server Generation. Every piece is automatically wrapped as an MCP server. The framework generates a tool definition for each action and a resource definition for each trigger. The MCP server exposes these through the Streamable HTTP transport with OAuth authentication. No additional configuration is needed — the MCP server is always available when the ActivePieces server is running.
Advanced Patterns
Pattern 1: Dynamic Dropdowns with Refreshers
Dropdown options can depend on other props. For example, a “Select Project” dropdown that refreshes when the “Organization” dropdown changes:
const projectDropdown = Property.Dropdown({
displayName: 'Project',
description: 'Select a project',
required: true,
refreshers: ['organization_id'], // Re-fetch when org changes
options: async ({ auth, propsValue }) => {
const orgId = propsValue['organization_id'];
if (!orgId) return { options: [], disabled: true };
const projects = await fetchProjects(auth, orgId);
return {
options: projects.map(p => ({
label: p.name,
value: p.id,
})),
};
},
});
Pattern 2: Dynamic Properties
When the available fields depend on a previous selection, use DynamicProperties:
const dynamicFields = Property.DynamicProperties({
displayName: 'Record Fields',
description: 'Fields for the selected record type',
required: true,
refreshers: ['record_type'],
props: async ({ auth, propsValue }) => {
const recordType = propsValue['record_type'];
const fields = await fetchFieldsForType(auth, recordType);
const props: Record<string, any> = {};
for (const field of fields) {
props[field.key] = Property.ShortText({
displayName: field.label,
required: field.required,
});
}
return props;
},
});
Pattern 3: Custom Auth with Multiple Fields
For APIs that need multiple authentication parameters (API key + subdomain + workspace ID):
export const customAuth = PieceAuth.CustomAuth({
props: {
subdomain: Property.ShortText({
displayName: 'Subdomain',
description: 'Your MyService subdomain (e.g., "acme")',
required: true,
}),
api_key: Property.ShortText({
displayName: 'API Key',
description: 'Your MyService API key',
required: true,
}),
workspace_id: Property.ShortText({
displayName: 'Workspace ID',
description: 'Your workspace ID',
required: true,
}),
},
async validate({ auth }) {
const { subdomain, api_key, workspace_id } = auth;
try {
await httpClient.sendRequest({
method: HttpMethod.GET,
url: `https://${subdomain}.myservice.com/v1/workspaces/${workspace_id}`,
headers: { Authorization: `Bearer ${api_key}` },
});
return { valid: true };
} catch {
return { valid: false, error: 'Invalid credentials' };
}
},
});
Production Deployment
Horizontal Scaling
# docker-compose.yml — multi-worker production
services:
activepieces:
image: activepieces/activepieces:latest
environment:
AP_MAX_CONCURRENT_JOBS: "100"
# ... base config
worker-1:
image: activepieces/activepieces:latest
command: ["node", "dist/main.js", "worker"]
environment:
AP_MAX_CONCURRENT_JOBS: "50"
# ... same env as activepieces
worker-2:
image: activepieces/activepieces:latest
command: ["node", "dist/main.js", "worker"]
environment:
AP_MAX_CONCURRENT_JOBS: "50"
# ... same env as activepieces
Backup and Recovery
# Backup PostgreSQL
pg_dump -h localhost -U postgres activepieces > backup_$(date +%Y%m%d).sql
# Restore
psql -h localhost -U postgres activepieces < backup_20260623.sql
# Backup Redis (optional — can be rebuilt from queue state)
redis-cli SAVE
cp /var/lib/redis/dump.rdb redis_backup.rdb
Monitoring
# ActivePieces supports OpenTelemetry for tracing
# Enable in docker-compose.yml:
AP_OPEN_TELEMETRY_ENABLED: "true"
AP_OPEN_TELEMETRY_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4318"
# Structured logging with pino
docker compose logs -f activepieces | pino-pretty
# Sentry integration for error tracking
AP_SENTRY_DSN: "https://your-dsn@sentry.io/project-id"
The Results
| Metric | Before (Zapier/Make) | After (ActivePieces Self-Hosted) | Improvement |
|---|---|---|---|
| Monthly automation cost (50K tasks) | $599 (Zapier Team) | $20 (VM + DB) | 96.7% reduction |
| Monthly automation cost (500K tasks) | $1,499 (Zapier Company) | $50 (scaled VM) | 96.7% reduction |
| Monthly automation cost (2M tasks) | $5,999 (Zapier Enterprise) | $100 (multi-worker) | 98.3% reduction |
| Integration count | 6,000+ (Zapier) | 600+ (ActivePieces) | 90% fewer, but growing |
| Setup time | 0 minutes (cloud) | 5 minutes (Docker) | Comparable |
| Data residency | Third-party cloud | Your VPC | Full control |
| AI agent integration | Limited (Zapier AI) | 280+ MCP servers | Unlimited |
| Embeddability | Not possible | Embed SDK + MIT license | Full |
| White-label | Not possible | Custom domain, logo, CSS | Full |
| Per-task cost | $0.05/100 tasks | $0.000001/100 tasks | 50,000x cheaper |
| License restrictions | Proprietary | MIT (no restrictions) | Full freedom |
What to Watch Out For
Beginner Advice:
- Set
AP_ENCRYPTION_KEYto exactly 32 hex characters before first startup. Changing it after data is written will corrupt your encrypted credentials (API keys, OAuth tokens). There is no recovery path. - Disable public signups immediately after creating your admin account. An unsecured ActivePieces instance is a credential leak waiting to happen — anyone who finds your URL can connect to your tools.
- Use
UNSANDBOXEDexecution mode for single-tenant deployments. The sandboxed modes add ~15 seconds of overhead per task. For a single team on your own infrastructure, the sandbox provides no meaningful security benefit over the OS-level isolation Docker already provides. - Start with the cloud free tier (1,000 tasks/month) before self-hosting. This lets you evaluate the tool without infrastructure overhead. Migrate to self-hosted when you hit the task limit.
- Test every step individually before enabling the flow. The “Test” button on each step runs it with your actual connection and shows the output. A flow that works end-to-end in the editor will work in production.
Lesson learned: “We deployed ActivePieces, built 15 flows, and enabled them all at once. Three of them failed because we hadn’t tested the error paths — a rate-limited API call, a malformed webhook payload, and a missing permission on a Google Sheet. The flows that worked were the ones we tested step by step. The ones that failed were the ones we tested end-to-end only. Test every step, not just the happy path.” — Senior Platform Engineer, mid-stage SaaS company
Lesson learned: “We tried to use ActivePieces as a direct Zapier replacement for a 200-flow deployment. The integration catalog gap hit us hard — 15 of our Zapier integrations had no ActivePieces equivalent. We had to build custom pieces for 8 of them. The pieces framework made it possible, but it took two weeks. If you’re migrating from Zapier, audit your integration list first. The 600-piece catalog covers the top 80% of use cases, but the long tail requires custom work.” — Head of Automation, e-commerce company
Lesson learned: “We ran ActivePieces in sandboxed mode for three months, wondering why our flows were so slow. Each task took 15-20 seconds. We switched to UNSANDBOXED mode and tasks completed in 300-500ms. The sandbox is designed for multi-tenant hosting where untrusted users run code on your server. For a single-team deployment on your own infrastructure, it’s unnecessary overhead. Read the execution mode documentation before you deploy, not after.” — DevOps Engineer, fintech startup
Next in the Open-Source AI Tools Mastery series: Danswer
Written by Nivant Labs Team
Engineer at Nivant Labs