MicroERP Deployment Guide¶
This document outlines the complete deployment architecture for MicroERP (Production, Second Production Node, and Staging).
1. Architecture Overview¶
| Environment | Branch | Hosting (Frontend) | Hosting (Backend) | Frontend URL | Backend URL |
|---|---|---|---|---|---|
| Production 1 | main |
Railway | Railway | https://merp25.up.railway.app |
https://merp25-api.up.railway.app |
| Production 2 | main |
Vercel (Prod) | Railway (Same) | https://ebosai.comhttps://merp25.vercel.app |
https://merp25-api.up.railway.app |
| Staging | stage |
Vercel (Preview) | Render | https://merp25stage.vercel.app |
https://merp25-backend.onrender.com |
2. Production Environment (Main)¶
Backend (Railway)¶
- Repo: GitHub
mainbranch - Service: Django Backend
- Domain:
merp25-api.up.railway.app - Database: Railway PostgreSQL (Internal)
Frontend 1 (Railway)¶
- Repo: GitHub
mainbranch - Service: Vite Frontend
- Domain:
merp25.up.railway.app - Note: Serves as the primary/fallback host.
Frontend 2 (Vercel)¶
- Repo: GitHub
mainbranch - Purpose: Primary global CDN fast access.
- Domains:
ebosai.com(Primary Custom Domain)merp25.vercel.app(Fallback)
3. Staging Environment (Pre-Production)¶
Backend (Render)¶
- Repo: GitHub
stagebranch - Platform: Render.com
- Domain:
https://merp25-backend.onrender.com - Database: Render PostgreSQL (or external staging DB)
Frontend (Vercel Preview)¶
- Repo: GitHub
stagebranch (linked tomerp25project) - Environment: "Preview" (Pre-Production)
- Domain:
https://merp25stage.vercel.app - Deployment Setup:
- Uses Preview Environment Variables to point to Render Backend.
- Domain is assigned via Settings -> Environments -> Preview.
4. Environment Variables Reference¶
When setting up new environments or debugging, ensure these variables are set correctly for the Frontend.
| Variable Name | Production Value (Railway/Vercel) | Staging Value (Vercel Preview) | Description |
|---|---|---|---|
VITE_API_URL |
https://merp25-api.up.railway.app |
https://merp25-backend.onrender.com |
Point to the correct Backend API |
VITE_SUPABASE_URL |
https://prod.supabase.co |
https://stage.supabase.co |
Your Supabase Project URL |
VITE_SUPABASE_ANON_KEY |
(Production Key) | (Staging Key) | Public Anon Key for Supabase |
5. Related Documentation¶
- Railway Deployment Guide - Step-by-step service creation, watch paths, build commands for Railway.
- Vercel Deployment Guide - Env var scoping per environment, domain assignment, preview protection.
- Render Deployment Guide - Media/FileField handling, persistent disk, static site setup on Render.
- Railway Optimization Guide - Managing credits and resources on Railway.
- Multi-Host Env Var Reference - Ready-to-paste env var blocks per platform (CORS, CSRF, Supabase).
6. Supabase Setup Guide¶
MicroERP uses Supabase PostgreSQL as the primary database AND Supabase Auth for JWT-based authentication. Both must be configured correctly per environment.
6.1 Project Strategy — How Many Supabase Projects?¶
[!IMPORTANT] The critical rule: Production data must be isolated from non-production data. Use a minimum of 2 Supabase projects.
| Supabase Project | Covers | Database Schema | Auth Users |
|---|---|---|---|
merp25-nonprod |
Dev + Stage | Shared (see 6.3) or separate (see 6.4) | Shared — same test credentials work on both |
merp25-prod |
Production only | public |
Real customer accounts only |
Why not 3 projects? Dev and stage share the same test data. The risk of mixing dev/stage data is negligible — the critical isolation boundary is non-prod vs prod.
6.2 Supabase Auth — URL Configuration¶
Each Supabase project must have all its frontend URLs registered or Supabase will reject auth callbacks with Invalid Refresh Token errors.
merp25-nonprod project (Auth → URL Configuration)¶
Site URL:
https://merp25stage.vercel.app
Additional Redirect URLs:
https://merp25stage.vercel.app/**
https://merp25dev.vercel.app/**
http://localhost:5173/**
merp25-prod project (Auth → URL Configuration)¶
Site URL:
https://ebosai.com
Additional Redirect URLs:
https://ebosai.com/**
https://merp25.vercel.app/**
https://merp25.up.railway.app/**
6.3 Option A — Shared Schema (Simplest, Recommended for UAT)¶
Dev and stage both point to the same Supabase project and the same public schema. This is acceptable because:
- Both environments use test data only
- Migrations applied on dev are immediately visible on stage
- Only one DATABASE_URL to manage for non-prod
Django DATABASE_URL setup:
| Environment | DATABASE_URL |
SUPABASE_URL / SUPABASE_ANON_KEY |
|---|---|---|
| Dev backend (Render) | postgresql://postgres.[ref]:[pass]@aws-...:5432/postgres |
Non-prod project values |
| Stage backend (Render) | ← same as Dev | ← same as Dev |
| Prod backend (Railway) | postgresql://postgres.[ref]:[pass]@aws-...:5432/postgres |
Prod project values |
Workflow:
1. Developer runs python manage.py migrate on dev
2. Stage picks up the same schema automatically (shared DB)
3. Before go-live, run python manage.py migrate on prod separately
6.4 Option B — Separate Schemas in One Supabase Project¶
Dev and stage share the same Supabase project but use separate PostgreSQL schemas (dev and stage). This keeps data isolated while staying on one project.
Step 1 — Create schemas in Supabase SQL Editor¶
-- Run once in Supabase SQL Editor (non-prod project)
CREATE SCHEMA IF NOT EXISTS dev;
CREATE SCHEMA IF NOT EXISTS stage;
-- Grant permissions to the postgres user
GRANT ALL ON SCHEMA dev TO postgres;
GRANT ALL ON SCHEMA stage TO postgres;
Step 2 — Set Django OPTIONS per environment¶
In settings.py, read the schema from an env var:
import os
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME', 'postgres'),
'USER': os.getenv('DB_USER', 'postgres'),
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST'),
'PORT': os.getenv('DB_PORT', '5432'),
'OPTIONS': {
'options': f"-c search_path={os.getenv('DB_SCHEMA', 'public')}",
},
}
}
Step 3 — Set DB_SCHEMA env var per environment¶
| Platform | Environment | DB_SCHEMA |
|---|---|---|
| Render | Dev backend | dev |
| Render | Stage backend | stage |
| Railway | Prod backend | public (prod project, default schema) |
Step 4 — Run migrations per schema¶
# On dev backend
DB_SCHEMA=dev python manage.py migrate
# On stage backend
DB_SCHEMA=stage python manage.py migrate
[!NOTE] Django migrations will create all tables inside the specified schema. Each schema is fully independent —
dev.core_companyandstage.core_companyare separate tables.
6.5 Environment Variables Reference (Updated)¶
Full updated reference including Supabase database variables:
Backend env vars (Render for dev/stage, Railway for prod):
| Variable | Dev (Render) | Stage (Render) | Prod (Railway) |
|---|---|---|---|
DATABASE_URL |
Non-prod Supabase DB URL | Same as dev (Option A) or same project (Option B) | Prod Supabase DB URL |
DB_SCHEMA |
dev (Option B only) |
stage (Option B only) |
public or omit |
SUPABASE_URL |
Non-prod project URL | Non-prod project URL | Prod project URL |
SUPABASE_SERVICE_ROLE_KEY |
Non-prod service key | Non-prod service key | Prod service key |
VITE_SITE_URL |
https://merp25dev.vercel.app |
https://merp25stage.vercel.app |
https://ebosai.com |
CORS_ALLOWED_ORIGINS |
https://merp25dev.vercel.app |
https://merp25stage.vercel.app |
https://ebosai.com |
Frontend env vars (Vercel per environment):
| Variable | Dev | Stage | Prod |
|---|---|---|---|
VITE_API_URL |
Render backend URL | Render backend URL | Railway backend URL |
VITE_SUPABASE_URL |
Non-prod project URL | Non-prod project URL | Prod project URL |
VITE_SUPABASE_ANON_KEY |
Non-prod anon key | Non-prod anon key | Prod anon key |
6.6 Go-Live Checklist (When Ready for Production)¶
- [ ] Create new Supabase project
merp25-prod - [ ] Copy schema (run
python manage.py migrate) against prod Supabase DB - [ ] Set Auth → URL Configuration in prod Supabase project (see 6.2)
- [ ] Update Railway backend env vars to prod Supabase credentials
- [ ] Update Vercel prod environment vars (
VITE_SUPABASE_URL,VITE_SUPABASE_ANON_KEY) - [ ] Update
settings.pyBASE_ALLOWED_ORIGINSor setCORS_ALLOWED_ORIGINSon Railway - [ ] Set
VITE_SITE_URLon Railway to the production frontend URL - [ ] Verify login works end-to-end on prod before announcing go-live