Skip to main content
As your workflow automation needs grow, you can scale Activepieces to handle more concurrent executions and higher throughput. This guide covers horizontal scaling strategies.

Scaling Architecture

Activepieces can be scaled by separating concerns into specialized containers:

Container Types

Activepieces supports three container types via the AP_CONTAINER_TYPE environment variable:
All-in-one containerRuns both API server and background workers:
AP_CONTAINER_TYPE=WORKER_AND_APP
Use for:
  • Development
  • Small deployments (< 100 workflows)
  • Single server setups
Pros:
  • Simple configuration
  • Minimal resource overhead
Cons:
  • Limited scalability
  • API and workers compete for resources

Horizontal Scaling Strategies

Strategy 1: Multiple All-in-One Instances

Simple scaling - Run multiple WORKER_AND_APP containers:
docker-compose.yml
services:
  activepieces-1:
    image: ghcr.io/activepieces/activepieces:0.79.0
    env_file: .env
    ports:
      - "8081:80"
      
  activepieces-2:
    image: ghcr.io/activepieces/activepieces:0.79.0
    env_file: .env
    ports:
      - "8082:80"
      
  activepieces-3:
    image: ghcr.io/activepieces/activepieces:0.79.0
    env_file: .env
    ports:
      - "8083:80"
      
  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
Nginx load balancer:
nginx.conf
upstream activepieces {
    server activepieces-1:80;
    server activepieces-2:80;
    server activepieces-3:80;
}

server {
    listen 80;
    
    location / {
        proxy_pass http://activepieces;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Strategy 2: Separate APP and WORKER Containers

Recommended for production - Dedicated containers:
docker-compose.yml
services:
  # API Servers (scale for HTTP traffic)
  app-1:
    image: ghcr.io/activepieces/activepieces:0.79.0
    environment:
      AP_CONTAINER_TYPE: APP
      AP_PM2_ENABLED: "true"  # Enable clustering within container
    env_file: .env
    deploy:
      replicas: 3
      
  # Workers (scale for job processing)
  worker:
    image: ghcr.io/activepieces/activepieces:0.79.0
    environment:
      AP_CONTAINER_TYPE: WORKER
      AP_WORKER_CONCURRENCY: "4"
    env_file: .env
    deploy:
      replicas: 5
Benefits:
  • Scale API and workers independently
  • Optimize resource allocation
  • Better fault isolation
  • Easier monitoring

Kubernetes Scaling

Horizontal Pod Autoscaler

Automatically scale based on CPU/memory:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: activepieces-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: activepieces
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 80
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Helm Configuration

values.yaml
# Enable autoscaling
autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80
  targetMemoryUtilizationPercentage: 80

# Resource requests/limits
resources:
  requests:
    cpu: 500m
    memory: 2Gi
  limits:
    cpu: 2000m
    memory: 4Gi

# Pod anti-affinity (spread across nodes)
affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100
      podAffinityTerm:
        labelSelector:
          matchLabels:
            app.kubernetes.io/name: activepieces
        topologyKey: kubernetes.io/hostname

Worker Configuration

Worker Concurrency

Control how many jobs each worker processes simultaneously:
.env
AP_WORKER_CONCURRENCY=4
AP_WORKER_CONCURRENCY
number
Guidelines:
  • CPU-bound workflows: concurrency = CPU cores
  • I/O-bound workflows: concurrency = CPU cores × 2-4
  • Default: 1 (safe default)
Example calculations:
  • 2 CPU cores, CPU-intensive: concurrency = 2
  • 4 CPU cores, API calls/webhooks: concurrency = 8-16

PM2 Clustering

Enable process clustering within a container:
.env
AP_CONTAINER_TYPE=APP
AP_PM2_ENABLED=true
When AP_PM2_ENABLED=true, PM2 starts one process per CPU core using cluster mode with -i 0.See docker-entrypoint.sh:20 for implementation.

Database Scaling

Connection Pooling

Adjust pool size based on instance count:
# Formula: (max_connections × 0.8) / instance_count
# Example: (100 × 0.8) / 4 = 20 per instance

AP_POSTGRES_POOL_SIZE=20
AP_POSTGRES_IDLE_TIMEOUT_MS=30000

PostgreSQL Max Connections

Increase PostgreSQL max connections:
# postgresql.conf
max_connections = 200
Or for managed databases:
Parameter Groups → max_connectionsFormula: {DBInstanceClassMemory/9531392}

Read Replicas

Offload read queries to replicas:
.env
AP_POSTGRES_HOST=primary-host
AP_POSTGRES_READ_REPLICA_HOST=replica-host
Activepieces doesn’t currently support read replica configuration. Consider using connection poolers like PgBouncer instead.

Redis Scaling

Redis Cluster

For high-throughput deployments, use Redis Cluster:
.env
AP_REDIS_TYPE=cluster
AP_REDIS_CLUSTER_NODES=redis-1:6379,redis-2:6379,redis-3:6379

Redis Sentinel

For high availability:
.env
AP_REDIS_TYPE=sentinel
AP_REDIS_SENTINEL_NAME=mymaster
AP_REDIS_SENTINEL_HOSTS=sentinel-1:26379,sentinel-2:26379,sentinel-3:26379
AP_REDIS_SENTINEL_ROLE=master

Job Retention

Control queue memory usage:
.env
# Keep failed jobs for 7 days
AP_REDIS_FAILED_JOB_RETENTION_DAYS=7

# Maximum 100 failed jobs
AP_REDIS_FAILED_JOB_RETENTION_MAX_COUNT=100

Load Balancing

Nginx

upstream activepieces_app {
    least_conn;  # Least connections algorithm
    server app-1:80 max_fails=3 fail_timeout=30s;
    server app-2:80 max_fails=3 fail_timeout=30s;
    server app-3:80 max_fails=3 fail_timeout=30s;
}

server {
    listen 80;
    server_name activepieces.yourdomain.com;
    
    # Increase timeouts for long-running workflows
    proxy_read_timeout 600s;
    proxy_send_timeout 600s;
    
    location / {
        proxy_pass http://activepieces_app;
        proxy_http_version 1.1;
        
        # Preserve client IP
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket support
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Kubernetes Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: activepieces
  annotations:
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-body-size: "100m"
spec:
  ingressClassName: nginx
  rules:
  - host: activepieces.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: activepieces
            port:
              number: 80

Monitoring Scaling

Metrics to Monitor

Monitor Redis queue depth:
# Using redis-cli
redis-cli LLEN bull:activepieces:waiting
redis-cli LLEN bull:activepieces:active
redis-cli LLEN bull:activepieces:failed
Scale workers when:
  • Waiting jobs > 100
  • Average wait time > 30s
Monitor worker CPU/memory:
# Docker
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# Kubernetes
kubectl top pods -l app=activepieces
Scale when:
  • CPU > 80%
  • Memory > 80%
Monitor API latency:
# Check health endpoint
curl -w "@curl-format.txt" -o /dev/null -s http://localhost:8080/v1/health
Scale APP containers when:
  • p95 latency > 500ms
  • Error rate > 1%
Monitor PostgreSQL connections:
SELECT count(*) FROM pg_stat_activity WHERE state = 'active';
SELECT count(*) FROM pg_stat_activity;
Adjust when:
  • Active > 80% of max
  • Connection errors in logs

Queue UI

Enable BullMQ Board for visual monitoring:
.env
AP_QUEUE_UI_ENABLED=true
AP_QUEUE_UI_USERNAME=admin
AP_QUEUE_UI_PASSWORD=secure_password
Access at: http://your-domain/admin/queues

Performance Optimization

Execution Mode

Use sandboxed execution for production:
.env
AP_EXECUTION_MODE=SANDBOX_CODE_ONLY

Timeouts

Adjust based on your workflow needs:
.env
# Maximum workflow execution time
AP_FLOW_TIMEOUT_SECONDS=600  # 10 minutes

# Webhook timeout
AP_WEBHOOK_TIMEOUT_SECONDS=30

# Trigger polling interval
AP_TRIGGER_DEFAULT_POLL_INTERVAL=5  # minutes

Caching

Enable piece caching:
.env
AP_PIECES_CACHE_MAX_ENTRIES=1000
AP_PRE_WARM_CACHE=true

Scaling Checklist

1

Database

  • Increase max_connections in PostgreSQL
  • Adjust AP_POSTGRES_POOL_SIZE per instance
  • Enable connection pooling (PgBouncer)
  • Setup database replication for HA
2

Redis

  • Configure Redis persistence
  • Setup Redis Sentinel/Cluster for HA
  • Monitor queue depth
  • Configure job retention
3

File Storage

  • Migrate to S3 from local storage
  • Enable S3 signed URLs
  • Configure lifecycle policies
4

Application

  • Separate APP and WORKER containers
  • Configure worker concurrency
  • Enable PM2 for APP containers
  • Setup load balancer
5

Monitoring

  • Setup metrics collection
  • Configure autoscaling
  • Enable queue UI
  • Setup alerting

Next Steps

Workers

Deep dive into worker architecture

Architecture

Understand system components

Database

Optimize database performance

Monitoring

Setup monitoring and alerts