Scale Mode

Scale mode adds a Redis job queue and a pool of workers, so orchestration runs started through the V2 API execute outside the API process.

Your main SynapseOrch instance keeps serving the UI and the APIs. Runs started through /api/v2 go onto a Redis queue, and separately deployed workers pull them off and execute them — as many workers, on as many machines, as you need.


What scale mode changes

StandaloneScale mode
/api/v2Every route returns 503 — "Scale mode is not enabled"A run returns 202 Accepted with a run_id at once
Where V2 runs execute—On workers, which take jobs from a Redis queue
UI, Chat, schedules and /api/v1In the API processStill in the API process — scale mode does not move them
StoreSQLite by default, or Postgres via SYNAPSE_DB_URLPostgres, shared by the API and every worker
V2 events—Redis Streams, delivered as SSE and replayable with Last-Event-ID
A worker dies mid-run—The job is picked up again after its timeout and runs again from the start
Load limits—Per-tenant rate limit, queued-run quota and global queue depth

Scale mode is decided when the process starts. A SynapseOrch instance is in scale mode when it starts with a Redis URL — REDIS_URL in its environment, or a Redis URL saved in Settings → Scale. Changing it takes a restart. The Enable scale mode switch in Settings → Scale does not start or stop scale mode; its only effect is to turn off local (stdio) MCP servers, which scale mode never runs.


When to enable scale mode

  • Many concurrent API runs — you start more workflow runs through the API than one process should execute alongside the UI
  • Long-running runs — you want API clients to get a run_id straight away and follow the run by SSE or webhook, rather than hold a request open
  • Separating load — you want run execution off the machine that serves the UI
  • Horizontal scaling — you want to add capacity by starting more worker containers rather than upsizing a single machine

What you need

ComponentRequiredNotes
RedisYesThe job queue, run event streams, cancellation signals. Compose runs Redis 7
PostgresYesThe store: definitions, settings, run state, the worker registry. The API and every worker must use the same database. Compose runs Postgres 16
Shared blob storageFor more than one hostThe vault, run logs, notifications and cached responses. Every process must use the same store: an S3 bucket (or MinIO or R2) configured on all of them — see S3 storage — or one shared SYNAPSE_BLOB_DIR. Compose shares a volume; across hosts without a bucket, mount the same network volume

Quick start

The quickest way to see scale mode working on one machine is the Docker Compose scale profile — see Deployment → Docker Compose. To add workers to an existing instance:

1. Point the main instance at Postgres and Redis

Set these in the main instance's environment and restart it:

SYNAPSE_DB_URL=postgresql://user:password@your-pg-host:5432/synapse
REDIS_URL=redis://your-redis-host:6379/0

A postgresql:// or postgres:// URL is converted to the postgresql+asyncpg:// driver form for you, so either spelling works. The scale layer uses the same database; SCALE_POSTGRES_URL is only needed to name a different URL for it, and must still reach the same database. A new Postgres database is set up on first start; it does not copy anything from a SQLite install. Bring workflows, agents, tools and MCP servers across with Import & Export.

You can also enter the Redis and Postgres URLs in Settings → Scale, check them with Test, and click Save scale config — then restart. SYNAPSE_DB_URL can only be set in the environment.

2. Start a worker

docker run -d \
  --name synapse-worker-1 \
  -e REDIS_URL="redis://your-redis-host:6379/0" \
  -e SYNAPSE_DB_URL="postgresql://user:password@your-pg-host:5432/synapse" \
  -e WORKER_CONCURRENCY=10 \
  -v /shared/synapse-blobs:/blobs \
  -p 9000:9000 \
  --restart unless-stopped \
  synapseorchai/synapse-ai-worker:latest

The worker needs the main instance's database in SYNAPSE_DB_URL; the image sets no default. It also needs the same blob storage: the main instance's blob directory mounted at /blobs, as here, or the same S3 bucket, with the same S3_* variables passed to both instead of the mount.

Verify the worker is healthy before sending jobs:

curl http://localhost:9000/health
{
  "status": "ok",
  "worker_id": "worker-4f1c2a9b7e30-1a2b3c4d",
  "address": "http://4f1c2a9b7e30:9000",
  "active_jobs": 0,
  "max_jobs": 10,
  "uptime_seconds": 12,
  "pg_connected": true,
  "redis_connected": true
}

The worker registers itself in Postgres as soon as it starts. It appears under Workers in Settings → Scale when you click refresh — the list is only shown by a main instance that is itself in scale mode.

3. Send a run

Create an API key in Settings → API keys, then:

curl -X POST http://localhost:3000/api/v2/orchestrations/{orch_id}/run \
  -H "Authorization: Bearer sk-syn-..." \
  -H "Content-Type: application/json" \
  -d '{"message": "Write a competitive analysis of Redis vs Kafka"}'

The response carries the run_id and a stream_url to follow it. See Architecture for the whole round trip.


Next steps

  • Architecture — how the components interact, Redis key patterns, Postgres tables, worker lifecycle
  • Configuration — the Scale settings screen and every environment variable
  • Deployment — Docker Run, Docker Compose, Kubernetes, production checklist

On this page