OpenSequence
DocsAPI referenceSDKs and CLIReference
Self-hosting

Configuration

Every SEQ_* variable, the queue backends and the roles.

Edit on GitHub
This page is generated from apps/server/src/config/env.ts by pnpm generate. Do not edit it by hand; change the source and regenerate.

Everything is configured through environment variables, Svix-style: you choose the database and the queue, and one image runs every role.

Variables

VariableTypeRequiredDefaultMeaning
SEQ_DB_DSNstringyesPostgres connection string. Only Postgres is supported. A transaction pooler is fine: no session-level features are used.
SEQ_QUEUEpostgres, redis, memoryno"postgres"The queue backend. postgres needs nothing else and is a transactional outbox; redis needs SEQ_REDIS_DSN; memory is for development and tests only.
SEQ_REDIS_DSNstringwith SEQ_QUEUE=redisRedis connection, required when SEQ_QUEUE=redis. Enable persistence on the Redis side.
SEQ_ENCRYPTION_KEYSstringyesEncryption keys for every stored secret, id:base64key[,id:base64key...]; the first entry encrypts, every entry decrypts. Generate one with oseq secrets new-key. Back it up with the database: without it the stored secrets are unreadable and must be re-entered.
SEQ_ADMIN_TOKENstringfor api and allThe operator token that creates projects and keys (/v1/admin/*). Required by the api and all roles. Long and random.
SEQ_PUBLIC_URLURLno"http://localhost:8080"The base URL providers call back: inbound webhooks, the Google OAuth return and the opt-out links. The OpenAPI document served by the instance lists it as its server.
SEQ_PORTnumberno8080HTTP port. The API for api and all; /healthz and /readyz only for worker.
SEQ_HOSTstringno"0.0.0.0"The interface to bind.
SEQ_ROLESapi, worker, allno"all"api serves HTTP, worker runs the scheduler and the queue consumers, all does both in one process.
SEQ_RUN_MIGRATIONSflag: 1 or truenoApply the seq and auth migrations at boot, serialized by a row lock so replicas starting together do not race.
SEQ_CONCURRENCYnumberno8Messages in flight per queue per replica.
SEQ_DISABLED_CHANNELScomma-separated listnoPlatform-wide kill switch per channel, comma-separated (sms,linkedin). Steps on a disabled channel are deferred, not skipped.
SEQ_PAUSEDflag: 1 or truenoPlatform-wide stop: the planner claims nothing while it is on. In-flight steps finish.
SEQ_DEV_MOCK_PROVIDERSflag: 1 or truenoEvery project uses the mock adapters: nothing reaches Google, Allo or Attio, sends land in the timeline, and POST /hooks/mock/\{slug\} simulates replies, bounces, bookings and calls. Refused when NODE_ENV=production.
SEQ_LOG_LEVELfatal, error, warn, info, debug, traceno"info"Pino log level.
SEQ_METRICSflag: 1 or truenoReserved for a Prometheus /metrics endpoint. Accepted by the schema; the endpoint is not served yet.
SEQ_DB_POOLnumberno10Postgres connections per process.
NODE_ENVstringno"development"production turns off pretty logs and refuses SEQ_DEV_MOCK_PROVIDERS.

Three rules are checked after parsing: SEQ_QUEUE=redis needs SEQ_REDIS_DSN; the api and all roles need SEQ_ADMIN_TOKEN; SEQ_DEV_MOCK_PROVIDERS is refused when NODE_ENV=production.

Queue backends

The queue interface is send, read with a visibility timeout, release, delete and archive; everything above it is identical across backends.

SEQ_QUEUEExtra infrastructureNotes
postgresnonethe default; the table seq.queue_messages with FOR UPDATE SKIP LOCKED; an enqueue joins the transaction that records the work (a transactional outbox)
redisRedis 7+higher throughput for large installs; an enqueue cannot join the database transaction, so the reaper's sweep re-enqueues anything recorded but never queued
memorynonedevelopment and tests only; the planner and the reaper rebuild work from the tables on boot

Because the database is the truth and queue messages are hints, a lost or empty queue never loses work. See Queues.

Roles

SEQ_ROLESRunsExposed publicly
apithe public API, inbound provider webhooks, the OAuth return, the opt-out page, /healthz and /readyzyes
workerthe scheduler (planner, signals, poll, reaper, retention, webhooks) and the queue consumers (email, SMS, signals, deliveries)no; it listens for /healthz and /readyz only
allboth in one processyes

A worker process still registers the API routes on its port; do not expose that port. Readiness for a worker also checks that the scheduler ran a job in the last two minutes.

Kill switches

SEQ_PAUSED=1 stops the planner platform-wide; SEQ_DISABLED_CHANNELS=sms defers every step of a channel. Both are read on every tick, so they take effect without a restart. Per-project switches exist too: PUT /v1/engine/flags/global and PUT /v1/engine/flags/channel:sms with { "value": false }.

On this page