Cover 01 · Decision 02 · Today 03 · What it is 04 · What we build 05 · Architecture 06 · Benefits 07 · Plan 08 · vs N8N 09 · Risks End

A platform in motion.

How Magic Omniverse adopts Windmill as the orchestration spine of a multi-tenant commerce platform — what we build on it, why it scales, and what falls away.

DocumentImplementation Overview
DecisionWindmill (AGPLv3)
ReplacesN8N · 29 workflows
StatusProposed
Thirteen tenants. Eight suppliers. One ERP integration on the way. One spine to hold it all together.
01

We're going with Windmill.

After scoring it head-to-head against Inngest across 19 dimensions weighted to our actual platform needs, Windmill won — narrowly, deliberately, and for reasons specific to where we are.

It is the only one of the candidates that can replace N8N end-to-end while also giving us code-driven workflows, internal admin tools, native cron and webhooks, and full polyglot scripting — all in one self-hosted, version-controlled platform.

One tool, one mental model, one place to look when something runs or fails. That consolidation is the prize.

The right answer wasn't the most powerful engine. It was the one that collapses three tools into one without losing what mattered.
02

Where we are right now.

A multi-tenant headless commerce platform across two boxes — DEV and NETCUP — running thirteen Medusa-powered storefronts, an AI agent layer on Mastra, and a constellation of integrations glued together by N8N.

The good: each tenant has its own Medusa instance, its own Postgres database, its own Redis, its own search. Blast radius is small. Per-tenant work is isolated. Adding a new customer is technically possible.

The bad: integration logic lives in 29 N8N workflows that drift between DEV and NETCUP, are invisible to version control, and were never designed to scale beyond glue. AI agents have started accreting inside those same workflows — a parallel agent system fighting Mastra for ownership.

The opportunity: an ERP integration for a real customer is on deck. So is Amazon. So is the rest.

13Medusa tenants
8Supplier connectors
29N8N workflows · legacy
1MCP / agent layer
03

A developer platform that orchestrates things.

Picture N8N's job — running schedules, webhooks, integrations between systems — but written by engineers, version-controlled in your monorepo, with native support for any language, and a built-in way to ship internal admin UIs.

It is a single open-source binary, written in Rust for speed, that does five things very well:

A · Scripts

Run code in any language

TypeScript, Python, Go, Bash, SQL, PowerShell. Each script is a function — testable, reusable, version-controlled. Imagine a directory of small useful programs that anything can call.

TS · PY · GO · BASH
B · Flows

Compose scripts into workflows

Chain scripts together. Branch on conditions. Loop over arrays. Run steps in parallel. Retry on failure. Either as code, or as visual flows — same engine, two surfaces.

VISUAL · OR · CODE
C · Apps

Internal UIs without React

Drag-and-drop admin tools that read from databases, run scripts, and present data. Think "tenant onboarding panel" or "ERP sync status dashboard" — built in an afternoon, not a sprint.

RETOOL-LIKE
D · Schedules

Cron jobs done right

Run anything on a schedule with full retry semantics, observability, and version history. Replaces every cron entry, every N8N schedule trigger, every "I'll write a script and add it to crontab" hack.

CRON · WITH MEMORY
E · Triggers

React to anything

HTTP webhooks, Postgres changes, Kafka topics, NATS events, MQTT, S3 buckets, email. The platform reacts. Connectors are written, not configured-then-prayed-over.

HTTP · DB · NATS · KAFKA
+ Vault

Secrets, properly

Per-workspace secret storage, encrypted at rest, never logged. We pair it with Vaultwarden for org-level secrets — Windmill holds runtime keys, Vaultwarden holds long-term credentials.

ENCRYPTED · SCOPED
Five primitives. Every integration we'll ever build is some combination of these.
04

Twelve concrete things — most of which we need anyway.

Every entry below is something either already running on N8N, planned for the next two quarters, or a known platform gap. Windmill isn't a new project. It's the home for work that's already on the roadmap.

01 · ERP

Bi-directional ERP sync

Order placed in Medusa → posted to ERP. Stock levels in ERP → reflected in Medusa. Master data flows both ways via custom APIs. Per-tenant config in Postgres so onboarding ERP customer #2 is a row insert, not a code change.

FLOWSEVENT-DRIVEN
02 · Marketplaces

Amazon & friends, outbound

Listings synced from Medusa to Amazon SP-API. Inventory updated as orders flow. Marketplace orders pulled back into Medusa for unified fulfilment. Each marketplace is its own script module behind a shared adapter interface.

FLOWSSCHEDULED
03 · Suppliers

Supplier feed orchestration

The eight existing supplier connectors — Spranz, Moxz, Langenberg, XD Connect, PF Concept, Mid Ocean, Toppoint, New Wave — move from N8N schedules and ad-hoc cron into Windmill flows. Same logic, observable, retryable, versioned.

SCHEDULEDRETRY-AWARE
04 · Tenant onboarding

One-click new tenants

Today: a manual checklist. Tomorrow: a Windmill flow that creates the database, runs migrations, provisions the Medusa instance, templates an Nginx vhost, requests a Let's Encrypt cert. End-to-end. Five minutes, fully reproducible.

FLOWSHIGH-LEVERAGE
05 · AI invocation

Mastra agents, called as tools

Windmill workflows call Mastra agents in magic-mcp over HTTP or MCP. Agents reason, tools act, workflows orchestrate. Three layers, one direction of dependency. AI stops accreting inside N8N nodes.

SCRIPTSMCP CLIENT
06 · Admin tools

Internal UIs as Apps

Tenant management dashboard. Sync status board. Order replay panel. Customer support tools. Each one a Windmill App — a few hours each instead of a Next.js project. Auth gated by Zitadel/WorkOS.

APPS
07 · Backups

Postgres + filesystem backups

Per-tenant database dumps to encrypted offsite storage. Filesystem snapshots of /mnt/data/pim_data. Retention policies enforced. Verified restorable monthly. All as scheduled flows with paged failure alerts.

SCHEDULEDOPS
08 · Webhooks

Payment, ERP, supplier callbacks

Stripe events. Mollie callbacks. Supplier fulfilment notifications. ERP push events. Every external party gets a signed Windmill webhook URL. Routing, validation, replay all handled in one place.

TRIGGERSHTTP
09 · Warehouse pipeline

Cross-tenant analytics replication

Per-tenant Postgres → ClickHouse warehouse for the AI/MCP layer to read across tenants. CDC-style sync via scheduled flows. Powers magic-mcp's cross-tenant tools without breaking tenant isolation.

FLOWSWAREHOUSE
10 · Notifications

Transactional email & alerts

Order confirmations, shipping updates, dunning emails, ops alerts. Templated, retried, logged. Pluggable provider — start with self-hosted Postal, swap if needed without touching workflows.

FLOWSEMAIL
11 · Deploys

Internal deploy & migration runners

Triggered by GitHub Actions or manually. Run database migrations across tenants, restart specific containers, roll forward or back, verify health checks. Deploys become reviewable artefacts, not artisanal SSH sessions.

FLOWSINFRA
12 · Customer ops

Support and lifecycle automation

Lead capture from contact forms. Quote generation. Customer-tier upgrades. Subscription renewals. Stripe Tax filings. Whatever moves a customer from one state to another runs through one observable spine.

FLOWSBUSINESS
05

Four layers, one direction.

Events flow upward. Decisions flow downward. Each layer does one job. Anything that doesn't fit cleanly into one of the four is the wrong shape.

DWorkflow / Orchestration
Windmill · Flows
Windmill · Scripts
Windmill · Apps
Windmill · Schedules
Windmill · Triggers
CReasoning / Agents
Mastra · magic-mcp
MCP Tools
LLM Calls
Memory
BCommerce / Domain
Medusa · Tenant 01
Medusa · Tenant 02
Medusa · Tenant 13
Payload CMS
PIM
AData / State
Postgres · per tenant
Redis
Meilisearch
ClickHouse · warehouse
MinIO · objects

Read it bottom-up.

State lives in databases. Domain logic lives in Medusa. Reasoning lives in Mastra. Orchestration lives in Windmill. Each layer can be swapped out independently because each layer talks to the one below through a clean interface.

Or read it top-down.

A trigger fires in Windmill — a webhook, a schedule, an event. A flow runs. The flow may call a Mastra agent for reasoning. The agent uses MCP tools to read or write commerce state. The result propagates back up.

06

Different audiences. Same platform.

A platform decision is only good if it earns its keep across every role that touches it. Here is how Windmill pays each one back.

Engineering

Code that lives in git.

  • Workflows reviewed in PRs, deployed via CI, rollback on demand
  • Type-safe TypeScript with shared Medusa types
  • Native polyglot — Python for AI/data, TS for commerce, Bash for ops
  • Local dev parity with production
  • Debugging by reading code, not chasing visual nodes
Operations

One pane of glass.

  • Every scheduled job, every webhook, every script in one history view
  • Failure alerts that point at exact run + line
  • Replay any run with one click
  • Backups, deploys, migrations all observable
  • Retire 4 N8N instances · reduce running surface
Business

Tenant onboarding in minutes.

  • New customer flow goes from checklist to one-click
  • ERP integrations re-templatable across customers
  • Marketplace expansion costs less per channel after the first
  • Internal admin tools shipped same-day, not next-quarter
  • Demos that work without "let me restart something"
Customers

Less drift, more trust.

  • Their integrations stop silently breaking
  • Order, stock, ERP data stays in sync — not "eventually" but reliably
  • Faster turnaround on custom feature requests
  • Their data isolated from other tenants by design
  • Onboarding feels like a product, not a project
07

Eighteen weeks. Four phases. AI does the lift.

Code is no longer the bottleneck — external coordination is. With AI-augmented build velocity, implementation collapses; the timeline is now paced by ERP customer schemas, Amazon's approval queue, and customer cutover windows.

The ERP project is still the forcing function. Use it to install the new pattern alongside the old. Let N8N die naturally as work moves through Windmill anyway.

~2wPhase 01 · Foundation
~4wPhase 02 · Compound
~4wPhase 03 · De-risk
~8wPhase 04 · Sunset
01 Weeks 1–2 · Foundation

Stand it up alongside the old.

Add Windmill to the monorepo as a Docker service. Build the ERP integration on it as the first production flow. Don't migrate anything yet — prove the pattern with real stakes.

  • Windmill server + workers + Postgres · day one
  • Per-tenant config schema in Postgres · never env vars
  • ERP bi-directional sync as flow #1 · gated by customer schemas
  • GlitchTip alongside for error tracking · half a day
  • Triage 29 N8N workflows · delete the dead ones same week

External gating: ERP customer's own pace on schema availability and credentials.

02 Weeks 3–6 · Compound

Use the pattern for everything new.

The shape exists. Marketplace integration, tenant onboarding automation, the most-painful N8N flows ported. ClickHouse warehouse stood up. Code is days, calendar is weeks — Amazon's approval queue sets the pace.

  • Amazon adapter as flow #2 · code in days, live after SP-API approval
  • Tenant onboarding becomes one trigger · 3 days end to end
  • Top 5 load-bearing N8N flows ported · 1 week
  • ClickHouse warehouse + first replication target · 1 week
  • First Windmill App: tenant management dashboard · 1 afternoon

External gating: Amazon SP-API approval typically 2–4 weeks in their queue.

03 Weeks 7–10 · De-risk

Address quiet, compounding risk.

The platform is running on Windmill for new work. Time to migrate the things that drag silently — auth, observability, infra. None of it user-visible. All of it pays compound interest.

  • WorkOS → Zitadel migration · before paying customer #5
  • k3s on a third VM · pilot one non-critical tenant
  • SigNoz for traces and metrics · OTel everywhere
  • NATS JetStream as event bus · only if volume justifies
  • MinIO for object storage if filesystem hits limits

External gating: Zitadel cutover windows — every tenant must re-auth, soak time non-negotiable.

04 Weeks 11–18 · Sunset

Retire what's earned its retirement.

By now five or fewer N8N workflows remain — all non-critical. Final sweep, retire the four DEV instances, reclaim the resources. The platform speaks one language end-to-end.

  • Remaining N8N workflows ported or sunset · 2 weeks
  • N8N containers retired · four instances reclaimed
  • Tenants progressively migrated to k3s · ~1 day per tenant
  • Reconsider Windmill vs. specialised engines · only if needed
  • Document the platform · onboard the next engineer in a day

External gating: tenant-by-tenant migration windows, scheduled around customer demand.

Implementation collapses. Coordination becomes the schedule.
08

Why it wins, for us specifically.

Eight reasons tied to our actual stack — not generic feature comparisons. Each one is a concrete pain Windmill removes or a capability N8N can't reach.

01 · Drift

The DEV / NETCUP problem disappears

N8N stores workflows in its own database. Our own CLAUDE.md says "do NOT import/export between DEV and NETCUP" — that's the drift speaking. Windmill workflows live as TypeScript / Python files in the monorepo. Same file deploys to both servers via existing CI. The drift problem becomes architecturally impossible.

SOURCE OF TRUTH
02 · Fan-out

Per-tenant work is one parameter, not 13 copies

Thirteen Medusa tenants. In N8N: duplicate a workflow 13 times, or build hairy "for each tenant" branching that breaks every time you add one. In Windmill: one parameterised flow, scheduled with each tenant_id. Add tenant 14 = insert one row in your config table. No workflow change.

13 → ∞ TENANTS
03 · Reuse

Your existing TypeScript becomes reusable

Your supplier connectors already exist as TS modules in magic_pim/src/modules/connectors/. N8N can't import them — you'd reimplement the logic in HTTP and Code nodes. Windmill imports them directly. One connector implementation, called from Medusa, agents, and workflows alike.

NO REIMPLEMENTATION
04 · Types

Type safety where it actually matters

Bi-directional ERP sync without type safety silently loses orders months after the integration ships. N8N's HTTP nodes treat responses as any. Windmill flows share types with your Medusa code — a renamed ERP field breaks the build, not production.

BUILD-TIME SAFETY
05 · Performance

Runtime is genuinely faster

Windmill's core is Rust — sub-100ms job startup, 1000+ concurrent jobs per worker. N8N is Node.js with per-node execution overhead, and the four instances on DEV are the workaround. 8 suppliers × 13 tenants = 104 sync jobs per cycle. Windmill finishes in minutes; N8N needs more boxes.

RUST CORE · SUB-100MS
06 · Agents

AI agents stop fighting Mastra

Today: agents accreting inside N8N nodes and Mastra agents in magic-mcp. Two parallel systems, two tool catalogs, two memories. Windmill flows call Mastra over HTTP / MCP — workflow orchestrates, agent reasons. Each layer one job. The split-brain ends.

ONE AGENT LAYER
07 · Apps

Internal admin tools come included

You will need: a tenant management dashboard, an ERP sync status board, an order replay panel, a customer support tool. In N8N world each is its own Next.js mini-project — days of work each. In Windmill, each is an App: drag a table, point it at a Postgres query, ship it the same afternoon.

RETOOL · INCLUDED
08 · Licence

Commercial paths stay open

N8N's fair-code Sustainable Use License restricts commercial-as-a-service use. Windmill's AGPLv3 doesn't, as long as you self-host unmodified. If you ever expose flow editing to your tenants — "let customers configure their own integrations" — only one of these two licences allows it.

AGPL3 · SELF-HOST
N8N is glue. Windmill is a development platform that happens to do glue.

And, side by side.

If the eight reasons above are the why, the table below is the what: a literal before-and-after of how the platform looks running on each.

TodayN8N

  • Workflows live in a database, not in git
  • DEV and NETCUP drift silently · "do not import/export between"
  • Four N8N instances on DEV — already smelling of scale strain
  • Fair-code license · not a clean OSS story
  • AI agents accreting inside workflow nodes
  • No type safety with Medusa types
  • Visual debugging disconnected from version history
  • Adding a tenant means duplicating workflows manually
  • Failures are seen if someone's looking at the UI
  • Internal admin tools — none, or built ad-hoc in React

TomorrowWindmill

  • Workflows are TypeScript / Python in magic_integrations/
  • One source of truth · same code on DEV and NETCUP
  • Single Windmill instance · workers scale horizontally
  • AGPLv3 · fully self-hosted, no vendor cap
  • Agents live in Mastra · workflows call them as services
  • Shared types between Medusa and integration code
  • Run history, logs, replay all in one place
  • Tenant config in Postgres · adding one is a row insert
  • Failures alert immediately · GlitchTip + run replay
  • Internal apps shipped same-day · drag and drop
09

What could go wrong.

No platform decision is free. These are the tradeoffs we know about, and how we plan to keep them from biting.

Risk · 01

Visual editor temptation

Windmill's flow editor exists. The same property that makes it a strict N8N superset is the same one that lets someone build a production-critical flow without a code review. Mitigation: production integrations must be code-defined. The visual editor is for one-off ops glue and prototypes only. Reviewable in PRs or it doesn't ship.
Risk · 02

Migration cost from N8N

Twenty-nine workflows is real work even if half are dead. Mitigation: never migrate for the sake of migrating. Port flows when their domain is being touched anyway — ERP work touches supplier sync, port the supplier flow then. A six-month sunset, not a sprint.
Risk · 03

AGPLv3 license

Copyleft triggers on network use of modified versions. Mitigation: we run unmodified Windmill behind authentication for our team and customers' workflows — not as a customer-facing service. Standard fully-self-hosted backend usage. Reviewed if we ever consider exposing Windmill UI directly to tenants.
Risk · 04

Newer in production-grade adoption

Windmill is younger than incumbents like Temporal or Inngest. Mitigation: we don't depend on Windmill-specific features in business logic. Connector code is plain TS modules; Windmill calls them. If we ever need to migrate, we keep the connectors and swap the runner.
Risk · 05

Event volume ceiling

Windmill's job model is less specialised for ten-thousand-events-per-second commerce than Inngest's event-driven core. Mitigation: we're nowhere near that today. If we hit it, we add Inngest just for the commerce event spine and keep Windmill for everything else. Not "either/or" forever.
A platform with one spine, four layers, and zero invisible glue.

Windmill isn't the destination. It's the shape that lets us build the destination — multi-tenant commerce that scales by adding rows, not by adding heroics.

Magic Omniverse · Architecture Brief Vol. 01 · 2026