Faktory is a background job server built by Mike Perham, the author of Sidekiq. Where Sidekiq is Ruby-specific, Faktory is language-agnostic: it's a standalone server that speaks a simple protocol over TCP, so you can push jobs from a Python app and process them with a Go worker — or any mix. If you have a polyglot stack, Faktory solves the problem of one shared, reliable queue.
How Faktory differs from Sidekiq
With Sidekiq, the queue is Redis and the worker logic is Ruby code that talks to Redis directly. Faktory inverts this: Faktory is the server (it embeds RocksDB for storage), and your workers — in any language — connect to it. This centralizes queue logic and gives you a web UI for free.
| Sidekiq | Faktory | |
|---|---|---|
| Languages | Ruby | any (Go, Python, Node, Ruby, ...) |
| Storage | your Redis | built-in (RocksDB) |
| Topology | library + Redis | dedicated server + client workers |
Deploying the Faktory server
Faktory ships the contribsys/faktory image. It listens on two ports: 7419 for the worker protocol and 7420 for the web dashboard.
The single most important production concern is persistent storage. Faktory keeps its job data in /var/lib/faktory (RocksDB). Run it without a persistent volume and you lose all enqueued and scheduled jobs on restart. Mount durable storage there.
# launch with persistence and production mode
faktory -e production -b 0.0.0.0:7419 -w 0.0.0.0:7420In production mode, Faktory requires a password.
Securing it
Faktory reads its password from a file or the FAKTORY_PASSWORD mechanism. Workers authenticate using a FAKTORY_URL that includes the password:
# workers connect with
FAKTORY_URL=tcp://:your-password@faktory-host:7419The web dashboard on 7420 should never be public without authentication — it can manipulate the queue. Put it behind your platform's auth or keep it on an internal-only route. Treat the Faktory password like a database credential and store it as a secret.
Connecting workers in any language
Workers use a Faktory client library for their language. A Go worker, for instance:
mgr := faktory_worker.NewManager()
mgr.Register("SendEmail", func(ctx context.Context, args ...interface{}) error {
// do the work
return nil
})
mgr.Concurrency = 20
mgr.Run()Deploy each worker as its own service pointing at FAKTORY_URL. You can run heterogeneous workers — a high-memory Python worker for data jobs and a lightweight Go worker for notifications — each on an appropriately sized compute tier.
Retries, scheduling, and the dead set
Faktory handles retries with exponential backoff server-side, supports scheduled (future) jobs, and moves permanently failed jobs to a dead set you can inspect in the dashboard. Because retry logic lives in the server, every worker language gets the same reliability semantics for free — a real advantage of the centralized design.
Open source vs Enterprise
The open-source Faktory covers the core: queues, retries, scheduling, the web UI. Faktory Enterprise adds features like batches, unique jobs, throttling, and expiring jobs. Decide which you need; the OSS edition is sufficient for most queue workloads.
Go-live checklist
- Persistent volume mounted at
/var/lib/faktory - Production mode + password set as a secret
- Web dashboard (7420) behind authentication
- Workers connect via
FAKTORY_URLwith the password - Worker services sized per workload, scaled by replicas
- Backup of the Faktory data volume
References
- [Faktory wiki & docs](https://github.com/contribsys/faktory/wiki)
- [Faktory Docker image](https://github.com/contribsys/faktory/wiki/Docker)
- [Faktory security](https://github.com/contribsys/faktory/wiki/Security)
- [Faktory clients (all languages)](https://github.com/contribsys/faktory#client-libraries)
Faktory runs as a PandaStack container service with persistent storage, and your polyglot workers deploy as separate services on the compute tiers that fit each one. Spin up a job server on the free tier at [dashboard.pandastack.io](https://dashboard.pandastack.io).