Deployment Guide
This page describes the deployment of the Mendix Deployment Hub onto its Neon (Lakebase Postgres) branch.
Services on the branch
neon.ts declares exactly what a branch needs:
flowchart TB
subgraph Neon["Neon branch: production"]
P[(Lakebase Postgres<br/>visitors + neon_auth users)]
A[Neon Auth<br/>Managed Better Auth]
F[Function: api<br/>Visitor API]
H[Function: hello<br/>smoke test]
end
E[Express + EJS app<br/>this server]
E -->|pooled DATABASE_URL| P
E -->|/auth proxy| A
A -->|users + sessions| P
E -->|X-Secret: APP_SHARED_SECRET| F
F -->|DATABASE_URL injected| P
Build and migrate
gantt
title Deployment pipeline
dateFormat HH:mm:ss
axisFormat %T
section Local
npm run build (tsc) :b1, 00:00:00, 40s
migrations (direct URL) :b2, after b1, 15s
npm start (Express) :b3, after b2, 5s
section Verify
E2E flows (docs + kas) :c1, after b3, 30s
Auth sign-up / sign-in :c2, after c1, 30s
Function health + report :c3, after c2, 15s
Connect facts
- The app connects to the pooled
DATABASE_URL(PgBouncer in transaction mode) — right for per-request web traffic. - The direct, unpooled URL (
DATABASE_URL_UNPOOLED) is reserved for migrations, which need a real session. - The Neon Function gets
DATABASE_URLinjected by the runtime; its public URL is guarded with theAPP_SHARED_SECRETheader. - Neon Auth (Managed Better Auth) stores users in the
neon_authschema of the same database, so auth state branches with the data.
pie title Where time goes on a page load (illustrative)
"EJS + markdown render" : 15
"Visit upsert (pooled)" : 25
"Mermaid draw (browser)" : 40
"Everything else" : 20