Deploy to Node.js
For an operator who would rather run on their own infrastructure than on Cloudflare. Cat Factory ships a runtime-neutral backend that runs as a standard Node.js service backed by PostgreSQL, with the same HTTP API as the Cloudflare deployment.
Just evaluating?
To try the whole product on one machine with Docker and a GitHub token, see Run Locally. It is the same runtime wired for a developer machine.
Your deployment project
As with the Cloudflare deployment, you assemble a small project on top of the published libraries: a thin package that depends on @cat-factory/node-server and calls its start(), plus your own .env and (if you containerize) a Dockerfile. To scaffold it, copy the deploy/node example directory, swap its workspace:* dependency for the published npm version, and point the config at your resources. You can layer in proprietary agents and providers the same way. For a step-by-step on the workspace layout, the local dev loop, and where custom code plugs in, see Set Up Your Deployment Repository.
Prerequisites
- Node.js 24+, required for native type stripping and
--env-filesupport. - A PostgreSQL database.
- Your own deployment project (see above), depending on the published
@cat-factory/node-server. - A GitHub App for authentication and repository operations (see Register the GitHub App).
- LLM provider API keys.
- A container runtime (Docker/Kubernetes/your scheduler) for per-run coding jobs.
Run directly with Node.js
From your deployment project:
cp .env.example .env
# Configure: DATABASE_URL, authentication, model keys
pnpm start
The schema migrates on boot, and the service listens on port 8787 by default.
Run with Docker
docker build -t cat-factory-node .
docker run --rm -p 8787:8787 \
--env-file .env \
cat-factory-node
How the Node.js runtime differs
The backend is runtime-neutral through port abstraction: the same @cat-factory/server HTTP layer serves both targets, and a conformance suite validates feature parity. The infrastructure adapters differ:
| Concern | Cloudflare | Node.js |
|---|---|---|
| Database | D1 | PostgreSQL (via Drizzle) |
| Durable execution | Cloudflare Workflows | pg-boss |
| Event streaming | Durable Objects | HTTP WebSocket support |
| Run jobs | Cloudflare Containers | Self-hosted runner pool |
Running coding agents
The Node runtime has no built-in per-run container. Inline agent kinds (architect, reviewer, …) work out of the box, but the repo-operating kinds (coder, mocker, blueprints, ci-fixer, conflict-resolver, merger, spec-writer, analysis) need a runner pool to run in. Container execution turns on once the deployment has the GitHub App credentials, a public URL, a session secret, and a runner-pool encryption key configured. Until then, container kinds fail loudly rather than faking success. See Configuration.
Running multiple instances
A single Node instance needs nothing extra: live board updates and the internal caches are in-process. When you run more than one Node replica behind a load balancer, point them all at a Redis instance with REDIS_URL. Redis then carries two cross-node signals so a browser connected to any replica sees live updates and every replica drops stale cache entries after a write on another node:
- Real-time event propagation between replicas.
- Cache invalidation between replicas.
Redis is only ever a message bus here, never a data store; a replica always repopulates its own in-memory state. ioredis is an optional dependency, so install it when you set REDIS_URL (boot fails with a clear message if it's missing). See Configuration → Multi-node coordination. The Cloudflare Worker needs none of this: its event hub and storage are globally addressed.
Node.js topology
┌─────────────────────────────────────┐
│ Node.js HTTP Service (port 8787) │
│ ├─ @cat-factory/node-server │
│ ├─ PostgreSQL database │
│ ├─ pg-boss job queue │
│ └─ HTTP WebSocket support │
└──────────────┬──────────────────────┘
│ spawn container jobs
┌──────────────▼──────────────────────┐
│ Docker / Kubernetes / Custom Runner │
│ executor-harness container image │
│ → coding agent execution │
└─────────────────────────────────────┘
For self-hosted execution at scale, point the service at a runner pool. See Run Jobs on Your Own Runners.
Next: set your secrets and toggles in Configuration.