Run Mendix applications natively on Snowflake using Snowpark Container Services (SPCS). No Mendix Cloud, no Kubernetes operator, no external infrastructure. The Mendix runtime runs as a container inside Snowflake, connected to a Snowflake-managed Postgres database, with file storage on Snowflake stages. Users authenticate via Snowflake identity and can query Snowflake data as themselves.
A controller-based deployment toolkit for running Mendix apps on SPCS:
- Controller (
Controller/) - A FastAPI service that runs inside SPCS and manages the full app lifecycle: provisioning services, storing constants as Snowflake secrets, and deploying new PAD versions without Docker rebuilds per app. upload-pad.ps1- The operator-facing deploy script. Uploads a Mendix PAD zip to the Snowflake stage and calls the controller API to trigger a deploy. No Docker build required per deploy.setup.ps1- One-time infrastructure setup: creates the controller role, secrets, stage, app registry table, and controller service.- Mendix Base Image (
Mendix Base Image/) - A generic Mendix runner image. Built once and shared across all apps. No app code baked in — the app is loaded from the stage at container startup. - SnowflakeSSO module - Mendix module that reads the
Sf-Context-Current-Userheader injected by SPCS, auto-logs users in using their Snowflake identity, and captures the caller token for querying Snowflake data as the end user. - mendix-spcs-howto.md - Full setup and deployment guide.
- mendix-spcs-caveats-and-ideas.md - Known limitations and future work.
┌─────────────────────────────────────────────────────────────────────┐
│ SPCS: MENDIX_DEPLOY_CONTROLLER │
│ FastAPI service managing all Mendix app deployments │
│ Endpoint: public (PAT-authenticated) │
└─────────────────────────────┬───────────────────────────────────────┘
│ creates / alters / suspends / resumes
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ app service │ │ app service │ │ ... │
│ mendix-base │ │ mendix-base │ │ │
└──────────────┘ └──────────────┘ └──────────────┘
│ │
└───────────────┘
│
Shared: compute pool, Postgres instance, EAI,
MENDIX_DEPLOY_STAGE (PAD zips)
- Compute: SPCS compute pool (CPU_X64_S or larger), shared across all app services
- Database: Snowflake Postgres instance; one database per app, auto-created at startup
- File storage: Snowflake internal stage mounted as a volume (files are queryable from SQL)
- Auth: Snowflake OAuth on the endpoint; SnowflakeSSO module maps Snowflake users to Mendix users
- Data access: Caller's rights with compound token; queries execute as the logged-in user
- Deploy: PAD zip uploaded to stage via Snow CLI; controller alters or restarts the service in-place, preserving the endpoint URL
- Mendix Studio Pro 10.24.19+ or 11.6.5+ (Portable App Distribution export)
- Snowflake account with ACCOUNTADMIN access
- Docker (Rancher Desktop with
dockerd (moby)engine, or Docker Desktop) - Snowflake CLI (
snow) 3.x+ - PowerShell 5.1+
Full one-time setup is in mendix-spcs-howto.md. The short version:
- Build and push the
mendix-baseimage once (shared across all apps) - Run
.\Controller\setup.ps1to provision the controller infrastructure - For each app, export a Portable App Distribution from Studio Pro and run:
.\Controller\upload-pad.ps1 `
-AppName "my-app" `
-PadPath "C:\path\to\MyApp_portable_20261201.zip" `
-ControllerUrl "https://<controller-ingress>.snowflakecomputing.app" `
-Token "<controller-pat>" `
-Config ".\Controller\controller-config.json" `
-AppConfig "C:\path\to\my-app-config.json" # first deploy onlySubsequent deploys omit -AppConfig. The script uploads the PAD to the Snowflake stage, triggers the controller, and polls until the app is READY.
No Docker build. Export a new PAD from Studio Pro and run upload-pad.ps1 without -AppConfig:
.\Controller\upload-pad.ps1 `
-AppName "my-app" `
-PadPath "C:\path\to\MyApp_portable_20261215.zip" `
-ControllerUrl "https://<controller-ingress>.snowflakecomputing.app" `
-Token "<controller-pat>" `
-Config ".\Controller\controller-config.json"Mendix microflows can query Snowflake tables using the logged-in user's identity (caller's rights). The SnowflakeSSO module captures a compound token (service + user), which authenticates JDBC connections over the internal Snowflake network. No EAI or external egress needed for this path.
See mendix-spcs-howto.md for setup details.
Files uploaded through Mendix land on a Snowflake stage and are immediately queryable:
LIST @ROB_TESTDB_NATIVEAPP.PUBLIC.MYAPP_FILESTORAGE_STAGE;
SELECT $1 FROM @ROB_TESTDB_NATIVEAPP.PUBLIC.MYAPP_FILESTORAGE_STAGE/export.csv (FILE_FORMAT => 'csv_format');SPCS compute pools charge per hour of runtime. A CPU_X64_S pool costs 0.11 credits/hour. The compute pool auto-suspends when all services are suspended (AUTO_SUSPEND_SECS = 3600). See the howto for scheduled suspend/resume task examples.
- SPCS endpoints get a fixed
<hash>-<account>.snowflakecomputing.appURL — no custom domains - Snowflake Postgres network policy must be updated when SPCS egress IP ranges rotate (current expiry: 2026-09-07)
- Trial Mendix license terminates the runtime after ~2 hours; a production license requires egress to
licensing.mendix.com - Caller's rights tokens expire after 30 minutes; the SnowflakeSSO refresh snippet must be present in the Main Layout
See mendix-spcs-caveats-and-ideas.md for the full list.