Deploy Windmill — Self-Hosted Retool & Automation Platform
Self-host Windmill — code-first internal tools, APIs & workflows
Just deployed
/var/lib/postgresql/data
Windmill-Worker
Just deployed
Windmill-Server
Just deployed
Deploy and Host Windmill on Railway
Windmill is an open-source developer platform for building internal tools, automations, and workflows — a self-hosted alternative to Retool, Airplane, and n8n, but code-first. Turn scripts in Python, TypeScript, Go, Bash, or SQL into UIs, APIs, cron jobs, and multi-step flows, with a fast Rust execution engine, auto-generated forms, and approval steps. This template deploys Windmill as a server, a worker, and PostgreSQL, pre-wired — a production automation platform, ready to add more workers as your job volume grows.
What This Template Deploys
| Service | Purpose |
|---|---|
| Windmill Server | Serves the web UI and API (MODE=server) |
| Windmill Worker | Executes scripts, flows, and scheduled jobs (MODE=worker) |
| PostgreSQL | Stores everything — scripts, flows, schedules, state, and the job queue |
All connect over Railway's private network. The server and worker run the same Windmill image in different modes, both pointed at PostgreSQL, which holds the entire state of the platform including its job queue.
About Hosting
Windmill's architecture is the thing to understand, and it's what makes it scale cleanly on Railway — this template wires it correctly.
Server and worker are the same image in different modes. Windmill runs one image (ghcr.io/windmill-labs/windmill) in two roles: MODE=server serves the UI and API and is exposed publicly, while MODE=worker pulls jobs from the queue and executes them and stays private. They don't talk to each other directly — they coordinate through PostgreSQL. This template deploys both, so you can run and automate workflows immediately.
Scale by adding more workers. Because workers are stateless and coordinate through the database, adding job throughput is just adding more worker services: duplicate the worker with the same image, MODE=worker, WORKER_GROUP=default, and the same DATABASE_URL. No message broker, no reconfiguration — the queue lives in Postgres and any worker picks up jobs.
PostgreSQL holds everything — back it up. Unlike systems that need a separate queue or broker, Windmill stores its entire state in PostgreSQL: scripts, flows, schedules, resources, secrets, run history, and the job queue itself. So Postgres is the single source of truth and the one component to back up. Migrations run automatically on first boot (about 30–60 seconds).
Native and standard workers for cost control. Windmill supports lightweight native workers (roughly 0.1 CPU and 128 MB RAM) for simple scripts, and standard workers (about 1 vCPU and 2 GB RAM) for heavier jobs with dependencies. Right-size your worker services to your workload so you're not paying for idle capacity — a real advantage on Railway's usage-based pricing.
Set the base URL to your domain. BASE_URL (your Railway or custom domain) tells Windmill its public address, so generated app links, webhooks, and approval URLs resolve correctly. This template wires it to your domain.
Code-first, with UIs and APIs for free. Every script automatically gets an auto-generated UI, a REST endpoint, and can be scheduled or chained into flows — so a Python or TypeScript function becomes an internal tool, a webhook, or a cron job without extra work.
Typical cost: ~$5–15/month on Railway for the server, a worker, and Postgres, scaling with how many workers you run. Windmill's core is open source (AGPL) and free.
How It Compares
| Windmill (self-hosted) | Retool | n8n | Airplane | |
|---|---|---|---|---|
| Approach | Code-first | Low-code UI | Node-based | Code-first |
| Languages | Python, TS, Go, Bash, SQL | JS | JS + nodes | Python, JS |
| Auto UI + API per script | Yes | Build it | Partial | Yes |
| Scaling | Add workers | Vendor | Add instances | Vendor |
| Data ownership | Full — your infra | Vendor | Full | Vendor |
| Self-hostable | Yes | Limited | Yes | No |
Retool is polished but low-code and largely vendor-hosted. n8n is great for node-based integration but less suited to serious code. Airplane is code-first but a paid cloud product. Windmill's edge is a fast, code-first platform where every script becomes a UI, an API, and a schedulable job — self-hosted, horizontally scalable by adding workers, and free of per-seat fees, with your code and data on infrastructure you own.
Deploy in Under 5 Minutes
- Click Deploy on Railway — the server, worker, and PostgreSQL build and wire together (~4 minutes)
- Confirm
DATABASE_URLis wired andBASE_URLis set to your Railway domain - Wait for migrations to finish (30–60 seconds) and the server to come up
- Open your Railway URL and create your admin account
- Write a script in Python or TypeScript, run it, and turn it into an app, API, or schedule
To handle more jobs, add another service with the same image and MODE=worker.
Common Use Cases
- Internal tools — turn scripts into admin panels and dashboards with auto-generated UIs
- Workflow automation — chain scripts into multi-step flows with branching and approvals
- API endpoints — expose any script as a REST endpoint or webhook instantly
Configuration
| Variable | Required | Description |
|---|---|---|
DATABASE_URL | Auto-injected | PostgreSQL connection — holds all state and the job queue |
MODE | Pre-set | server on the web service, worker on the worker service |
BASE_URL | Required | Your public domain — for app links, webhooks, and approvals |
WORKER_GROUP | Pre-set | default — the group workers belong to |
| Postgres connection | Auto-injected | Via Railway reference |
Same image, two modes — scale with workers. The server (
MODE=server) and worker (MODE=worker) share one image and coordinate through Postgres. Add moreMODE=workerservices with the sameDATABASE_URLto increase throughput — no broker needed.
Postgres is everything, so back it up. Scripts, flows, schedules, secrets, and the job queue all live in PostgreSQL. Migrations run automatically on first boot. Set
BASE_URLto your domain for correct links.
Dependencies for Windmill Hosting
- Railway account — ~$5–15/month for the server, a worker, and Postgres
- PostgreSQL (included and wired via Railway references)
- Additional worker services (same image,
MODE=worker) to scale job throughput - Optional: external PostgreSQL (Neon, RDS, Cloud SQL) for large production setups
Deployment Dependencies
- Windmill GitHub Repository
- Windmill Documentation
- Windmill Self-Host Guide
- Railway Private Networking
Implementation Details
The template deploys Windmill's core architecture on Railway: a server service and a worker service, both running the same ghcr.io/windmill-labs/windmill image (a pre-compiled Rust binary) distinguished only by the MODE variable (server versus worker), plus a Railway-managed PostgreSQL database, all connected over the private network via DATABASE_URL. The server serves the frontend and API and is exposed publicly; the worker pulls and executes jobs and stays private. They coordinate exclusively through PostgreSQL rather than communicating directly.
PostgreSQL stores the entire state of Windmill — scripts, flows, schedules, resources, secrets, run history, and the job queue — so no separate message broker is required, and it is the single backup target. Migrations run automatically on first boot (roughly 30–60 seconds). BASE_URL is set to the Railway domain so generated app links, webhooks, and approval URLs resolve correctly.
Scaling is horizontal: because workers are stateless and share the database queue, additional worker services with the same image, MODE=worker, WORKER_GROUP=default, and DATABASE_URL increase throughput without reconfiguration. Windmill distinguishes lightweight native workers (about 0.1 CPU, 128 MB RAM) from standard workers (about 1 vCPU, 2 GB RAM), letting resources be right-sized. Scripts in Python, TypeScript, Go, Bash, and SQL each gain an auto-generated UI, a REST endpoint, and scheduling.
Frequently Asked Questions
What's the difference between the server and worker? They run the same image in different modes: MODE=server serves the UI and API, MODE=worker executes jobs. They coordinate through PostgreSQL, not directly. This template deploys both so Windmill works out of the box.
How do I add more workers? Create another service with the same ghcr.io/windmill-labs/windmill image, set MODE=worker, WORKER_GROUP=default, and the same DATABASE_URL. It joins the pool and picks up jobs from the shared queue — no broker or extra config.
Which languages can I use? Python, TypeScript/JavaScript, Go, Bash, and SQL. Each script gets an auto-generated UI, a REST endpoint, and can be scheduled or chained into flows.
Is it really a Retool alternative? Yes — Windmill turns scripts into internal tools with auto-generated UIs, plus APIs, schedules, and flows. It's code-first rather than drag-and-drop, self-hosted, and free of per-seat fees.
Why Deploy Windmill on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Windmill on Railway you get a code-first automation platform with the architecture wired — a server, a worker, and PostgreSQL connected, migrations run automatically, and easy scaling by adding more workers. Build internal tools, APIs, and workflows in your own languages, self-hosted on infrastructure you own.
Template Content
Windmill-Worker
ghcr.io/windmill-labs/windmillWindmill-Server
ghcr.io/windmill-labs/windmill