Back to articles
Technology Insight

Deploying Windmill.dev on a VPS: The High-Performance Workflow Engine Replacing n8n and Temporal

June 1, 2026

Introduction: The Evolution of Workflow Automation

In the modern DevOps and software engineering landscape, workflow orchestration has become a core architectural pillar. For years, development teams have relied on tools like n8n for low-code automation and Temporal for complex, code-first stateful orchestration. However, a significant gap has persisted between these two paradigms: low-code platforms often lack developer-centric guardrails, while code-first frameworks introduce immense infrastructure complexity.

Enter Windmill.dev—an open-source, ultra-fast, and developer-first alternative that bridges this gap. Built on Rust and Postgres, Windmill offers the raw speed and resource efficiency that modern VPS (Virtual Private Server) deployments require, serving as a viable, high-performance replacement for both n8n and Temporal. This guide provides a comprehensive overview of Windmill's architecture and a step-by-step technical blueprint for deploying it on a self-hosted VPS.

Why Windmill.dev is Replacing n8n and Temporal

Before diving into the deployment mechanics, it is essential to understand why engineering teams are shifting their workloads to Windmill. Choosing a workflow engine requires balancing performance, maintainability, and ease of use.

1. The Performance Paradox: Rust vs. Node.js and Go

While n8n is highly intuitive, its Node.js architecture can become a bottleneck under heavy concurrent loads, leading to high memory consumption. Temporal, on the other hand, is incredibly robust but requires a complex ecosystem of workers, matching engines, and external databases (like Cassandra or Elasticsearch) just to operate efficiently. Windmill circumvents these limitations by utilizing a Rust-based core. It executes scripts in Python, TypeScript, Go, Bash, and Rust with minimal overhead, delivering sub-millisecond scheduling latency and exceptional throughput on minimal hardware footprints.

2. Developer-First Experience with True Code-First Flexibility

Unlike traditional low-code platforms that lock users into proprietary visual builders, Windmill treats code as a first-class citizen. Every step in a Windmill workflow is simply a standard script with typed inputs and outputs. Windmill automatically generates UI forms based on your code's type definitions (such as Pydantic models in Python or TypeScript interfaces). This allows developers to build complex logic using git-controlled code while allowing non-technical stakeholders to trigger workflows via clean, auto-generated user interfaces.

Pre-requisites for VPS Deployment

To ensure a production-ready, highly available Windmill instance, your VPS should meet the following minimum specifications:

  • CPU: 2 vCPUs (Dedicated CPU threads are recommended for high-throughput production workloads).
  • RAM: 4 GB minimum (8 GB recommended if running intensive Python or TypeScript heavy runtimes).
  • Storage: 40 GB SSD/NVMe.
  • OS: Ubuntu 22.04 LTS or Ubuntu 24.04 LTS.
  • Network: A static public IP address with ports 80 and 443 open.
  • Domain: A registered domain or subdomain (e.g., windmill.yourcompany.com) pointed to your VPS IP via an A record.

Step-by-Step Guide: Deploying Windmill via Docker Compose

The most reliable and maintainable method to deploy Windmill on a self-hosted VPS is using Docker Compose. This encapsulates the web frontend, the worker pool, and the backend database into isolated, easily upgradable containers.

Step 1: System Update and Docker Installation

First, connect to your VPS via SSH and update the system packages to their latest versions:

sudo apt update && sudo apt upgrade -y

Next, install Docker and the Docker Compose plugin if they are not already present on your system:

sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
curl -fsSL [https://download.docker.com/linux/ubuntu/gpg](https://download.docker.com/linux/ubuntu/gpg) | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] [https://download.docker.com/linux/ubuntu](https://download.docker.com/linux/ubuntu) $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.p/docker.list > /dev/null
sudo apt update && sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y

Step 2: Configuring the Windmill Environment

Create a dedicated directory for your Windmill installation to keep configuration files organized:

mkdir -p /opt/windmill && cd /opt/windmill

Windmill requires a configuration file to define environment variables, database credentials, and security keys. Create a .env file within this directory:

DATABASE_URL=postgres://windmill_user:secure_password_here@db:5432/windmill?sslmode=disable
WM_SECRET_KEY=generate_a_long_random_string_here
DATABASE_PASSWORD=secure_password_here
BASE_URL=[https://windmill.yourcompany.com](https://windmill.yourcompany.com)
Security Note: Always replace secure_password_here and generate_a_long_random_string_here with strong, cryptographically secure values to safeguard your workflow state and secrets store.

Step 3: Writing the Docker Compose File

Create a docker-compose.yml file in the same directory. This configuration sets up PostgreSQL as the state store, the Windmill server to handle API traffic, and Windmill workers to execute asynchronous tasks:

version: '3.8'

services:
  db:
    image: postgres:15-alpine
    restart: unless-stopped
    volumes:
      - db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
      POSTGRES_USER: windmill_user
      POSTGRES_DB: windmill
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U windmill_user -d windmill"]
      interval: 5s
      timeout: 5s
      retries: 5

  windmill-server:
    image: ghcr.io/windmill-labs/windmill:main
    restart: unless-stopped
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - WM_SECRET_KEY=${WM_SECRET_KEY}
      - BASE_URL=${BASE_URL}
    depends_on:
      db:
        condition: service_healthy

  windmill-worker:
    image: ghcr.io/windmill-labs/windmill:main
    restart: unless-stopped
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - WM_SECRET_KEY=${WM_SECRET_KEY}
      - MODE=worker
    depends_on:
      db:
        condition: service_healthy

volumes:
  db_data:

Step 4: Launching the Services

With the environment and compose configuration ready, initialize the containers in detached mode:

sudo docker compose up -d

Verify that all containers are running correctly by checking their status:

sudo docker compose ps

Securing Your Instance with an Nginx Reverse Proxy and Let's Encrypt

Exposing port 8000 directly to the internet is unsecure. To protect data in transit, we must place Windmill behind an Nginx reverse proxy secured with Let's Encrypt SSL certificates.

1. Install Nginx and Certbot

sudo apt install nginx certbot python3-certbot-nginx -y

2. Configure Nginx for Windmill

Create a new Nginx server block configuration:

sudo nano /etc/nginx/sites-available/windmill

Paste the following configuration, replacing windmill.yourcompany.com with your actual domain:

server {
    listen 80;
    server_name windmill.yourcompany.com;

    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $$host;
        proxy_set_header X-Real-IP $$remote_addr;
        proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $$scheme;
        
        # WebSocket support required for Windmill logs
        proxy_http_version 1.1;
        proxy_set_header Upgrade $$http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Enable the site configuration and restart Nginx:

sudo ln -s /etc/nginx/sites-available/windmill /etc/nginx/sites-enabled/
sudo systemctl restart nginx

3. Obtain an SSL Certificate

Execute Certbot to automatically fetch and configure an SSL certificate from Let's Encrypt:

sudo certbot --nginx -d windmill.yourcompany.com

Follow the interactive prompts to complete the configuration. Certbot will automatically rewrite the Nginx files to enforce secure HTTPS connections.

Post-Deployment Architecture and Scale Considerations

Once you navigate to your domain and log in with the default administrator credentials ([email protected] / password), you will immediately notice the responsiveness of the interface. However, maintaining this velocity at scale requires adhering to production best practices.

Horizontal Worker Scaling

One of Windmill’s structural advantages over n8n is its native capability to scale workers independently of the web server. If your workflows bottleneck due to resource-heavy data processing scripts, you can scale your worker pool instantly by running:

sudo docker compose up -d --scale windmill-worker=3

Database Maintenance

Because Windmill relies entirely on PostgreSQL for task state, job queues, and audits, your database will grow continuously. Implement automated automated backup strategies (such as pg_dump cron jobs synced to secure object storage) and periodically review log retention policies within Windmill settings to prevent storage exhaustion.

Conclusion

Windmill.dev represents a paradigm shift in workflow orchestration. By combining the ultra-low latency and safety of a Rust core with a developer-centric, code-first design language, it provides an optimized engineering experience that outpaces n8n in pure performance and vastly simplifies the operational footprint required by Temporal. Deploying Windmill on a self-hosted VPS gives your organization complete data sovereignty, predictable infrastructure expenditures, and an enterprise-grade automation engine ready to scale with your backend requirements.

Deploying Windmill.dev on a VPS: The High-Performance Workflow Engine Replacing n8n and Temporal | DPTCloud