Windmill Labs
Windmill

Windmill vs Tines

Eight questions teams ask during a bake-off, with an honest answer on each one for where Windmill or Tines is the better pick.

WindmillWindmill in one sentence

An open-source workflow engine and developer platform to build and orchestrate all your internal software: scripts, workflows, data pipelines, AI agents and internal apps. Every step is real code in 20+ languages, running on your own workers, with a local dev loop and whole-workspace Git sync.

TinesTines in one sentence

A workflow automation platform for security and IT teams. A Tines story is a diagram of connected actions, which Tines describes as "analogous to playbooks, use-cases, or workflows". Pages add forms and approval screens, and Cases adds an incident console as a paid add-on. Tines does not publish its platform source.

01 · What you can build

Which internal software can you build and orchestrate?

Windmill is built to centralize and orchestrate all your internal software in one place. Scripts, workflows, data pipelines, full-code apps, AI agents and operator UIs run on a single runtime, with shared resources, auth and observability. Tines covers workflow automation plus the surfaces the security and IT playbooks in its library need: pages for human input, and cases for incident work as a paid add-on. For security work specifically, see how teams run SOAR on Windmill, including a demo of an automated incident-response flow.

PrimitiveWindmillWindmillTinesTines
Chain steps with branching, retries and approval steps
Recurring jobs with retries, error handling and alerting
Standalone functions with their own input UI, API endpoint and schedule, with no wrapping workflow
ETL and syncs over large payloads, with SQL steps and object storage
Partial
Agents that call tools, branch on outputs and run as a step inside a workflow
Forms, request and approval screens for the people who run the automation
Custom dashboards and admin tools built in React or Svelte
Case management console
A collaborative incident view with comments, observables and reporting
Via appsPaid add-on

Two rows need their caveat spelled out. Tines has no standalone script primitive: code runs inside a Run Script action in a story, and a story is callable over HTTP only through a webhook entry action (Workflows as APIs). Data pipelines are marked partial because the Run Script action's maximum timeout is 110 seconds and its runtime is Python only, which rules out long transforms in-platform. On the other side, Windmill has no dedicated case-management primitive: you build that view as an app, while Tines Cases ships one with comments, observables and reporting, as an add-on on paid plans.

02 · Target

Who is each platform built for?

Tines is built so a security or IT analyst can ship a playbook without an engineer, and that is a real advantage on day one. Windmill contests the same ground differently: non-developers compose flows and apps visually from deployed scripts, and anyone can build with AI in an isolated fork that an engineer reviews before it reaches production.

Primary audience

WindmillWindmill

Developer-led teams. Engineers own the platform end-to-end: code, Git, local dev, workspace forks, code review, CI/CD, AI coding tools, infrastructure as code. The automation is source files, so it is reviewed the way application code is.

TinesTines

Security and IT teams. Tines' own workflow capability matrix counts 86 areas under Security and 102 under IT operations, and its solutions pages extend from there to finance, people, RevOps and legal. An analyst can build a story from configured actions without an engineer, which is the fastest path from alert to playbook.

Building without writing code

WindmillWindmill

A member with a Compose role builds flows and apps in the visual flow editor from scripts engineers already deployed, with no code of their own. Members who build with AI get the Write code capability, and review and isolation protect production rather than their role. Protection rulesets and custom workspace roles are Enterprise only.

TinesTines

The storyboard is the main authoring surface, so configuring actions is the normal way to build. Change control turns a live story read-only and routes edits through drafts, a review request and an approval before they are pushed, which is how engineering oversight is applied.

Reviewing a change

WindmillWindmill

A change is a diff over files: scripts, flow YAML, resources, schedules and permissions. It can be reviewed in a pull request, by an engineer who has never opened the Windmill UI, and run locally first.

TinesTines

A change request renders the changed actions side by side on the storyboard, with comment threads per row and an activity trail. Review happens in Tines, against action configuration rather than source files. Story versions keep snapshots you can preview, clone, export or restore.

03 · Build experience

How do you build on each platform?

This is the biggest difference between the two platforms. Windmill makes real code the default unit of work: any language, any package, a local dev loop, and the whole workspace in Git where a coding agent and a reviewer both read it. Tines makes configured actions the default unit, with code available inside a Run Script action on the python3.13 runtime, and governs changes with drafts and approvals inside the product.

WindmillWindmill

The script is an ordinary Python file. Its signature generates the input form and the JSON schema, the url_reputation type is a shared resource, and httpx is installed from the import. The flow definition only wires steps together: it references the script by path and passes values with JavaScript expressions over results.

from typing import TypedDict
import httpx

class url_reputation(TypedDict):
base_url: str
api_key: str

def main(reported_url: str, rep: url_reputation) -> dict:
r = httpx.get(
f"{rep['base_url']}/v1/url",
params={"q": reported_url},
headers={"Authorization": f"Bearer {rep['api_key']}"},
timeout=30,
)
r.raise_for_status()
score = r.json()["score"]
return {"url": reported_url, "score": score, "block": score > 70}
TinesTines

Code lives inside a Run Script action, as a main(input) function that reads the incoming event and returns one. Everything else is action configuration: the story is a set of typed actions with an options block, positions and source_ids / receiver_ids links, as shown in Tines' own API docs.

import boto3

def main(input):
# Return early if credential fetch failed
if not input.get('AwsCredentials', {}).get('Success', False):
return input
creds = input["AwsCredentials"]
s3 = boto3.client(
's3',
aws_access_key_id=creds['AccessKeyId'],
aws_secret_access_key=creds['SecretAccessKey'],
aws_session_token=creds['SessionToken'],
)
buckets = s3.list_buckets()
return {'buckets': [bucket['Name'] for bucket in buckets['Buckets']]}

Authoring

WindmillWindmill

Write scripts in 20+ languages in the script editor or in your own IDE. Windmill parses the function signature to generate the input UI, the JSON schema and the argument types. Dependencies resolve automatically into a per-script lockfile. Arguments pass between flow steps as return values, read as results.<step_id> in the flow editor.

TinesTines

Drag actions onto the storyboard and configure each one. The core action types are Webhook, Receive Email, Send Email, HTTP Request, Condition, Event Transform, Send to Story and AI Agent. Actions emit events to their receivers, and values are referenced with Tines formulas. An action can also have a failure path.

Running code

WindmillWindmill

Code is the default unit, not an escape hatch. TypeScript (Bun, Deno, Node.js), Python, Go, Bash, SQL, PowerShell, PHP, Rust and more, each with any npm, PyPI, Go, Maven or Cargo package as a first-class import. Timeouts are yours to set, per instance and per flow step, and the same script runs unchanged on your laptop.

TinesTines

The Run Script action is "currently limited to the python3.13 runtime", with a default timeout of 10 seconds and a maximum of 110, and a 250MB unzipped package limit. On Cloud it executes on AWS Lambda in Tines' AWS environment next to your tenant. Custom runtimes let you upload your own environment, and Tines notes they "currently only support Python".

Local dev & IDE

WindmillWindmill

Pull the whole workspace to disk with the Windmill CLI, edit with native language tooling (LSP, type-checking, linting), run wmill dev for a live-reload preview of a flow or app, and push back. The VS Code extension validates flow.yaml in real time.

TinesTines

Building happens in the browser, on the storyboard. For automated management there is a Terraform provider for stories and other resources, and a REST API. Tines does not document a CLI or a local engine for running a story on your machine.

Building with AI

WindmillWindmill

wmill init writes AGENTS.md, CLAUDE.md and per-language skill files so Claude Code or Codex works against real source files in your repo, plus an MCP server for the workspace. In-product AI sessions build in a fork, and the model provider is yours.

TinesTines

Workbench builds and edits stories in-app, and the first-party Tines Stories MCP server exposes the same story-authoring capabilities to Claude Code, Codex or Cursor over OAuth. What the agent produces is actions on the storyboard in your tenant, not files in your repo. AI features default to Claude via AWS Bedrock, and you can configure your own provider.

Resources & secrets

WindmillWindmill

Resources (typed JSON for credentials and connection info) and variables are first-class and shared across scripts, flows and apps, encrypted at rest and scoped by folders and groups. External secret backends (Vault, Azure Key Vault, AWS Secrets Manager) are Enterprise only.

TinesTines

Credentials are referenced from action configuration with the CREDENTIAL formula key and substituted at run time, so the value is never in the action options. Types include text, JWT, OAuth 2.0, AWS, HTTP Request, mutual TLS and multi-request, plus guided connect flows per product.

Git & change control

WindmillWindmill

Full IaC: scripts, flows, apps, resources, variables, schedules, folders, groups and permissions are files in Git, deployed with the CLI and Git sync. Internal tooling ships like application code: PRs, reviews, rollbacks, CI. Git sync is free for up to 2 users; beyond that is Enterprise only.

TinesTines

Native Git is a Tines 3B feature ("Git integration comes as standard"), not a Stories one. In Stories, change control gives drafts, a review request, comments, approval and a push, and story versions keep snapshots. Git-style version control is reached through the Terraform provider or by exporting story files. Story syncing across teams and tenants is Enterprise only.

04 · Integrations

How does the platform integrate with your existing stack?

Windmill treats the package ecosystems as the integration catalog: a new integration is an import plus a typed resource. Tines treats HTTP plus a credential as the universal connector, with an importable library of security and IT stories to start from. Teams we hear from name custom integrations as the place where the configured-action model starts to cost them time.

Connecting out

WindmillWindmill

Any npm, PyPI, Go or Maven package is a first-class import with automatic per-script dependency resolution, so you call the vendor's own SDK with type inference and auto-completion. 50+ pre-built resource types cover databases (Postgres, Snowflake, BigQuery), SaaS (Slack, GitHub, Notion, OpenAI) and infrastructure (S3, Redis, Kafka): paste a key into a typed form and the resource is shared across scripts, flows and apps. A community Hub has reusable scripts and flows.

TinesTines

The HTTP Request action is the universal connector, which is why Tines describes itself as vendor-agnostic and says it "talks to any API or Model Context Protocol (MCP)". A library of pre-built stories covers common security and IT tools and can be imported into a tenant and adapted. There is no package-import model: a new integration is HTTP calls plus a credential, not a dependency you add.

Receiving events

WindmillWindmill

Native triggers for HTTP, cron, email, Kafka, NATS, Postgres CDC, SQS, MQTT and WebSocket. Each is a typed primitive: configure the topic, subject or path, attach it to a script or flow, and Windmill handles the connection and consumer state. Every script also gets a webhook URL and an HTTP endpoint for free.

TinesTines

Webhook and Receive Email are action types, so an inbound alert or a reported phishing email starts a story directly. Actions can also "run on a schedule or upon receiving an event", which covers polling an external system. Message brokers such as Kafka, NATS or MQTT are not among the core action types.

Extending

WindmillWindmill

A new integration is a script with a new import: save and run, no restart and no image rebuild, in the web editor, the CLI and Git sync alike. Custom logic can be exposed as a typed script, packaged as a resource type, or published to the workspace Hub for the team.

TinesTines

Three routes. Drop into a Run Script action for Python logic. Upload a custom runtime to control the Python version and dependencies. Or expose your own stories as tools by building an MCP server in Tines, so an external AI client calls the lookups and approvals you have already modeled as actions.

05 · Migration & lock-in

How hard to get in, and how hard to get out?

Tines is the quicker start for a playbook its library already covers, and its export is a complete description of the logic. Windmill keeps the switching cost low at the other end: every step is standard code that keeps running after you leave. Moving a story over is a rebuild, and a coding agent does most of it.

Getting in

WindmillWindmill

Paste a function body into the script editor: Windmill infers the arguments, generates the UI and resolves the dependencies. Or pull the workspace to disk and let a coding agent write the scripts and the flow. Triggers, schedules, variables and apps move one at a time.

TinesTines

Fast for the cases its library already covers: import a story and adapt it. There is no YAML or code to learn before the first working playbook, which is the main reason teams get to production quickly.

Getting out

WindmillWindmill

Step logic is already standard code (TypeScript, Python, Go, Bash, SQL) that runs anywhere, and the CLI exports the whole workspace as plain files. What you lose by leaving Windmill is the runtime, not the step code.

TinesTines

Story files "contain all actions and their sources/receivers" and "do not contain any event data", so the logic is portable as a description. Rebuilding it elsewhere means reimplementing each action type, the formulas and the event model, since the configuration is not runnable outside Tines. Python inside Run Script actions ports as-is.

Export the story

From the storyboard, export the story as a story file. It holds every action and its sources and receivers, and no event data.

Rebuild it with a coding agent

Run wmill init in a synced folder: it writes AGENTS.md, CLAUDE.md and per-language skill files that tell Claude Code or Codex how Windmill scripts and flows are laid out. Then point the agent at the export.

Review and push

Preview the flow locally, then push the folder with its triggers and schedules. Everything stays files on your machine, so the diff is reviewable before anything runs.

npx -y windmill-cli@latest init --use-default

claude "Rebuild ./story-export.json as Windmill scripts and a flow under f/security/"

npx windmill-cli workspace add
npx windmill-cli sync push --includes 'f/security/**' --include-triggers --include-schedules

There is no packaged Tines migration skill yet, so the agent works from the export and the general Windmill skills. Credentials are never in a story file: each one is connected once in Windmill as a resource or a secret.

06 · Enterprise requirements

Audit logs, observability, security, performance

Tines is stronger than Windmill's free tier on two specific axes worth naming: SSO on every tenant including Community Edition, and audit logs with two years of retention and scheduled S3 export. Windmill puts more of the runtime story in your hands: your own workers, published benchmarks, no step timeout, and self-hosting with no license key.

Observability

WindmillWindmill

Real-time streaming logs, per-run inputs, outputs and duration, worker queue metrics and a Prometheus exporter, with a trace ID on every job. Job run details are retained up to 30 days on the free self-hosted edition and without limit on Enterprise.

TinesTines

Each action has status and log tabs, plus action monitoring to notify on events or errors. Dashboards chart records and cases, and can email a snapshot on a schedule. Tines also tracks time saved per action, which is unusual and useful for reporting to a non-technical sponsor.

Audit logs

WindmillWindmill

A full trail of who ran, edited and deployed what, with forwarding to your SIEM. On self-hosted, audit logs require Enterprise Enterprise only. On the Team cloud plan they are retained 7 days.

TinesTines

"We automatically capture an audit log any time a user changes any piece of data", read via UI and API by tenant admins or holders of the AUDIT_LOG_READ permission, with two years of retention and scheduled exports to S3 every 15 minutes. Enhanced AI audit logs record each model invocation with token counts and the full response.

Security

WindmillWindmill

SOC 2 Type II compliant. RBAC, SSO for up to 10 users, encrypted secrets at rest and sandboxed execution in open source. Uncapped SSO, SAML, SCIM and process isolation controls are Enterprise only.

TinesTines

SSO is supported "on all Tines Stories tenants, paid and Community Edition alike", which is more generous than Windmill's free tier. Admin settings also cover IP access control, action egress control, a custom certificate authority and login notices.

Multi-tenancy & isolation

WindmillWindmill

Multiple isolated workspaces on one instance, each with their own users, resources, secrets and access controls, plus forks and dev workspaces. The free self-hosted edition is capped at 3 workspaces and 50 users; unlimited is Enterprise only.

TinesTines

Tenants hold teams, and credentials and resources are owned per team. Pushing one centrally-managed story out to many teams or tenants uses story syncing, which Tines documents as available to MSSP and Enterprise customers Enterprise only.

Performance

WindmillWindmill

Around 10ms cold starts, and dedicated-worker mode Enterprise only keeps runtimes and dependencies pre-warmed. Published reproducible benchmarks cover Airflow, Prefect, Temporal, Kestra, Hatchet and Windmill. Tines is not in that dataset, so we make no claim about it.

TinesTines

Tines does not publish benchmark figures. The documented limit that shapes design is the Run Script action timeout: a default of 10 seconds and a maximum of 110, so long work is split across actions or pushed to an external system.

Deployment

WindmillWindmill

Self-host the open-source core with Docker or Kubernetes, from one VPS to a large cluster, with no license key and no conversation. Managed cloud is also available.

TinesTines

Self-hosted Tines Stories ships as a set of Docker images and runs in ECS, EKS, AKS, GKE, OpenShift, VMware or Docker Compose. The docs ask you to contact your account executive or customer success manager first, who then puts you in touch with the people who grant image access.

07 · Licensing & pricing

Open source, pricing, and self-hosting?

Windmill's core is AGPLv3 and self-hostable with no license key, and Enterprise pricing is published per seat and per compute unit. Tines is proprietary: the free edition is generous on users and connectors but capped at 3 live workflows, paid editions are "Get pricing", and self-hosting starts with a conversation with your account team. High cost is one of the two reasons we hear most often from teams moving off it.

Open-source license

WindmillWindmill

AGPLv3 core, free and unlimited to self-host. Enterprise features (uncapped SSO, dedicated workers, audit logs, external secret backends, protection rulesets) ship in a separate proprietary codebase. Managed cloud available.

TinesTines

Tines does not publish its platform source. Its Terraform provider is open source under MPL-2.0. Self-hosting is supported through Docker images obtained via your account team.

Pricing

WindmillWindmill

Public per-seat and per-compute-unit pricing on the pricing page, with a calculator. A member who only runs and views what others built counts as half a seat. No sales call needed to know what it costs.

TinesTines

The Free edition gives "Unlimited users, spaces, and connectors", "3 live workflows" and a "One time $50 AI allowance". Paid editions are listed as "Get pricing", so there is no public price. Tines 3B states "We use a platform license model".

AI costs

WindmillWindmill

No AI meter of its own. You configure a provider (OpenAI, Azure OpenAI, Anthropic, Mistral, Google Gemini, Groq, OpenRouter, Together AI, AWS Bedrock, or any OpenAI-compatible endpoint including a local Ollama), and model calls are billed by that provider at its rates.

TinesTines

AI features default to Claude hosted through AWS Bedrock and are metered in credits, where one credit equals $0.01. Bringing your own AI provider is supported, and listed as a paid-edition capability on the pricing page.

08 · Verdict

The verdict

Tines' homepage now says "AI made everyone a builder. Now give them somewhere to build." We agree with that, and we would go one step further: when AI builds the automation, what it builds should be real code you own. Any language, your own packages, open source, running on your own workers, with a price you can read on a page.

Tines Stories can be a good fit if your work is security and IT playbooks its library already covers, analysts need to ship without an engineer, and in-product drafts and approvals are the governance model you want. Its export is honest, SSO is on every tenant including the free edition, and audit logs are deep.

Windmill covers the same work, and every step is an ordinary script. Any of 20+ languages instead of one Python runtime, any package instead of HTTP plus a credential, no 110-second ceiling, a local dev loop, and the whole workspace in Git where a coding agent and a human reviewer read the same files. The runtime scope is wider too: the same platform runs standalone scripts with their own API endpoint, data pipelines, AI agents, and low-code and full-code internal apps, on shared auth, secrets and observability. Non-developers are not shut out: they compose flows and apps visually from deployed scripts, or build with AI in a fork that an engineer reviews before it ships.

The two reasons we hear most often from teams who move are cost and the ceiling on custom integrations, and both follow from the same design choice. If you are deciding between the two, the fastest way to judge is to spend an afternoon in each: export one real story, and let a coding agent rebuild it on Windmill.

Frequently asked questions

Build your internal platform on Windmill

Scripts, flows, apps, and infrastructure in one place.