Deployment
Deploy to Gencow Cloud — frontend, backend, static assets, environments, CI/CD
Gencow supports four deployment modes: gencow dev (real-time backend with watch), gencow deploy (one-shot backend deploy), gencow deploy --static (backend + built frontend), and gencow static (frontend files only).
Environments
Gencow BaaS provides two isolated environments:
| Dev | Production | |
|---|---|---|
| Domain | *.gencow.dev |
*.gencow.app |
| Access | All plans | Pro+ only |
| Command | gencow dev / gencow deploy |
gencow deploy --prod |
| Database | app_{name} schema |
app_{name}-prod schema |
| Env vars | gencow env set KEY=VAL |
gencow env set KEY=VAL --prod |
Self-hosted users: You manage your own deployment infrastructure.
gencow deployis not available for cloud targets. Connect to your own PostgreSQL viaDATABASE_URL.
Plan Limits
Public self-serve cloud plans are Hobby, Pro, and Scale. Enterprise is handled through a separate inquiry path.
| Plan | App slots | Realtime connections/app | Production deploy |
|---|---|---|---|
| Hobby | 5 | 50 | Not available |
| Pro | 10 | 500 | Available |
| Scale | 50 | 5,000 | Available |
App slots count dev apps and production apps separately. For example, a first gencow deploy --prod creates a separate production app and consumes one additional slot.
Realtime limits apply to concurrent WebSocket subscriptions for one app. HTTP requests and static page views are metered separately through platform credits.
Authentication
Login
gencow loginThis opens your browser for Device Auth:
- A code is displayed in the terminal
- Browser opens to
gencow.app/cli-auth - Confirm the code in the browser
- Token is saved to
~/.gencow/credentials.json
Check Status
gencow whoami
# → User ID, Token info, ExpiryLogout
gencow logoutDeploying Marketplace Templates
Marketplace templates are cloned as complete source projects. Do not initialize them again with gencow init . --force; that command can overwrite Gencow-owned scaffold files.
gencow templates clone <template-slug> my-app
cd my-app
bun install
gencow login
gencow deployFor templates that include a frontend build, deploy backend + static files together:
bun run build
gencow deploy --static dist/On the first deploy, Gencow creates a new cloud app for your account and writes local app metadata to gencow.json. Marketplace downloads intentionally exclude gencow.json, .env, .gencow/, platform tokens, and preview app bindings.
Backend Development (Real-time)
Start real-time development — watches for changes and auto-deploys:
gencow devWhat Happens
- Creates app on platform (if first time) → assigns unique
appId - Bundles
gencow/+package.json+ lockfiles →tar.gz - Uploads bundle to platform
- Platform provisions: PostgreSQL database + isolated container
- Watches for file changes → auto-redeploys
- Saves
appIdtogencow.json
Dev Output
Gencow Dev — Watch Mode
▸ 앱: null-mint-9625
▸ URL: https://null-mint-9625.gencow.app
✓ 초기 배포 완료 (42.5 KB)
⏳ Watching for changes...One-Shot Deploy (Dev)
Deploy your backend to the dev environment without watch mode:
gencow deployThis is useful for CI/CD pipelines or when you want a quick push without staying attached.
Production Deploy (Pro+)
gencow deploy --prodPro+ only. Hobby plan users will see a blocking message with instructions to use
gencow deploy(dev) orgencow devinstead.
On first production deploy, Gencow automatically creates a separate production app (my-app-prod):
🚀 First production deployment!
This will create a production app: my-app-prod
Proceed? (y/N): y
✓ Prod 앱 생성 완료: my-app-prod
▸ URL: https://my-app-prod.gencow.app- DB isolation: Separate database schema (
app_my-appvsapp_my-app-prod) - Process isolation: Separate port, separate process
- Env vars copied: Dev env vars are copied to prod on first deploy
- Slot cost: Prod app counts as 1 app slot
- gencow.json updated:
prodAppfield added automatically
Subsequent gencow deploy --prod deploys directly to the prod app.
Rollback
Roll back to the previous deployment:
gencow deploy --rollback # Rollback dev app
gencow deploy --rollback --prod # Rollback prod app- Code only: Restores the previous bundle (database is NOT rolled back)
- Safe: Requires additive-only migrations (column additions, not deletions)
- Bundle retention: Last 5 deployment bundles are kept on disk
- Environment-aware: Rollback targets dev by default, use
--prodfor production
🔄 롤백 완료! (1.2s)
▸ 롤백: #5 → #4
▸ 번들: a1b2c3d4
▸ URL: https://my-app-prod.gencow.app
⚠ 코드만 롤백되었습니다. 데이터베이스는 변경되지 않았습니다.Static Deployment (Frontend)
Deploy a built frontend to your dev environment. For new Gencow apps, prefer Vite + React; use Next.js only for existing Next.js projects or explicit SSR requirements:
# Build your frontend first
VITE_API_URL=https://my-app.gencow.app npm run build
# Deploy the build output only
gencow static dist/Auto-Detection
If you don't specify a directory, Gencow auto-detects in this order:
dist/→out/→build/→.next/out/
gencow static # auto-detects dist/Production Static Deploy (Pro+)
gencow static --prod dist/Guardrails
The CLI automatically warns about common issues:
- API references in static files: If your build contains
/api/queryor/api/mutationand no backend is detected, Gencow warns that static hosting has no API server - Fullstack command: If you need backend + frontend together, use
gencow deploy --static dist/
When you run gencow static from a frontend subdirectory, Gencow detects the parent backend root for gencow.json and gencow.config.js metadata. The build output directory is still resolved from the frontend directory where you ran the command.
Fullstack Deployment (Recommended)
For projects with both backend and frontend, gencow deploy --static automatically detects and deploys both:
# 1. Build frontend with the backend URL
VITE_API_URL=https://my-app.gencow.app npm run build
# 2. Deploy — backend is auto-detected and deployed first, then frontend
gencow deploy --static dist/When gencow/ is detected in the current or parent directory, the CLI:
- Deploys the backend first
- Deploys the frontend static files
- Reports both URLs
To upload only frontend files, use the static-only command:
gencow static dist/CORS:
*.gencow.appsubdomains are automatically allowed. For external frontends, usegencow cors add https://your-frontend.com. Custom domains are same-origin, so they do not need CORS entries.
CORS for External Frontends
You only need CORS when your frontend is hosted outside Gencow, such as Vercel or Netlify.
gencow cors add https://myapp.vercel.app
gencow cors list
gencow cors remove https://myapp.vercel.app*.gencow.appsubdomains are allowed automatically.localhost:*is allowed automatically for local development.gencow domain set myapp.commakes your frontend and API same-origin, so no CORS setup is needed.- If the app is
running, changes are hot-reloaded immediately. If the app isidle, the setting is saved now and applied on the next wake/cold start.
Environment Variables
By default, gencow env commands target the cloud app. For local development, use .env file directly.
Set Variables (Cloud)
# Single variable → cloud
gencow env set OPENAI_API_KEY=sk-...
# Multiple → cloud
gencow env set DATABASE_URL=postgres://... SECRET_KEY=abc123Local dev: Edit
.envfile directly —gencow devloads it automatically. See Local Development.Idle apps: cloud env changes are stored immediately even when the app is
idle. A running app hot-reloads them right away; an idle app picks them up on its next wake.
Self-hosted Platform Runtime Config
Self-hosted platform operators can keep admin-only settings that do not yet have a dashboard UI in a JSON file:
GENCOW_PLATFORM_CONFIG_FILE=/etc/gencow/platform-config.jsonUse this for platform-owned document conversion and OCR settings such as default models, provider order, prompts, and custom VLM endpoints. The file is read at platform startup, so restart the platform after changing it. For user-facing conversion API usage and routing behavior, see Document Conversion.
These settings must stay platform-side. Tenant app workers should not receive
GENCOW_PLATFORM_CONFIG_FILE, GENCOW_DOCUMENT_*, PLATFORM_OPENAI_KEY, or
PLATFORM_GOOGLE_KEY.
Example document conversion settings:
{
"document": {
"safeAuto": {
"maxPaidFallbackCredits": 200
},
"providers": {
"kordoc": {
"url": "http://kordoc.internal:5004",
"token": "replace-me",
"timeoutMs": 120000
},
"forceOcrOrder": ["custom_vlm", "openai", "gemini", "ocr"],
"customVlm": {
"url": "https://vlm.internal/v1/ocr",
"token": "replace-me",
"timeoutMs": 60000
}
}
}
}document.convert() safe auto uses local/self-hosted providers first. Gemini,
OpenAI, OCR, and custom VLM fallback only run when the workflow request sets
paidFallback: true or chooses a paid provider explicitly.
DEV/QC/PROD should set document.providers.kordoc.url to the internal Kordoc
convert server when Kordoc-backed formats are enabled; the platform process does
not execute Kordoc locally. Production/non-loopback Kordoc convert servers
should require INTERNAL_TOKEN / KORDOC_INTERNAL_TOKEN; set
document.providers.kordoc.token to the same value.
List Variables
gencow env list # Dev app env vars
gencow env list --prod # Prod app env vars (Pro+)Remove Variables
gencow env unset OPENAI_API_KEY # Dev app
gencow env unset OPENAI_API_KEY --prod # Prod app (Pro+)Push Local .env to Cloud
gencow env push # Push .env → dev app
gencow env push --prod # Push .env.production → prod appSecurity: Environment variables are encrypted at rest.
.envis gitignored by default.Requires:
gencow.jsonmust exist (created bygencow devorgencow deploy). Must be logged in (gencow login).
Database Migrations
Gencow uses a local-generate-first migration workflow. The CLI generates SQL migration files locally, bundles them with your code, and the platform applies only the pending migrations on deploy.
How It Works
schema.ts → [deploy: drizzle-kit generate] → gencow/migrations/ → [bundle] → [Platform: migrate()]gencow deploy(andgencow dev) automatically runnpx drizzle-kit generatebefore bundling- The generated
gencow/migrations/files are bundled into the deploy archive - On the platform,
drizzle-orm/migratorapplies only the pending migrations using__drizzle_migrationshistory table
Interactive prompts supported: If drizzle-kit detects a column rename, it will ask you in the terminal. The prompt passes through (
stdio: inherit).
⚠️ Generate failed? If
drizzle-kit generatefails (e.g., missingdrizzle.config.ts), the deploy continues with a warning. Ifgencow/migrations/is still missing, the platform will skip schema migration.
Workflow
# First deploy — everything is automatic:
gencow deploy # dev deploy
gencow deploy --prod # production deploy
# 1. drizzle-kit generate runs locally → creates gencow/migrations/
# 2. gencow/ is bundled (including migrations/)
# 3. Platform applies pending migrations
# After schema.ts changes:
gencow deploy # same flow — platform applies only the new migrations
# Want to preview what migrations will be generated?
gencow db:generate # generate only, no deployMigration Output
When deploying, you'll see:
✓ Schema → migrations synced ← drizzle-kit generate ran automatically
✓ Bundle created: 42.5 KB ← gencow/migrations/ included in bundleOn the platform:
[provisioner] my-app: migrations applied ✓drizzle.config.ts
The drizzle.config.ts in your project root controls migration generation:
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "postgresql",
schema: ["./gencow/schema.ts", "./gencow/generated/auth-schema.ts"],
out: "./gencow/migrations", // ← must be inside gencow/ to be bundled
tablesFilter: ["!_system_*", "!_gencow_*"],
...(process.env.DATABASE_URL
? { dbCredentials: { url: process.env.DATABASE_URL } }
: {}),
});Important: The
outpath must be insidegencow/so migrations are included in the deploy bundle. The default template sets this to./gencow/migrations.
Platform-Owned Runtime Tables
Gencow reserves two internal table families:
_system_*— framework/system settings and storage metadata_gencow_*— workflow runtime state (_gencow_workflows, steps, events)
Your app should treat them as read-only platform internals:
- keep them excluded from Drizzle with
tablesFilter: ["!_system_*", "!_gencow_*"] - never declare them in
schema.ts - never ship migrations that alter or drop them
If these filters are missing, Drizzle can interpret platform tables as app schema drift and attempt rename/drop prompts during generate or push.
Migration Commands
gencow db:generate # Generate SQL files from schema.ts (no DB connection needed)
gencow db:migrate # Apply pending migrations to cloud DB
gencow db:push # Instant schema sync without migration files (dev only)| Command | When to use |
|---|---|
db:generate |
After every schema.ts change |
db:migrate |
Manually apply migrations to cloud DB |
db:push |
Quick prototyping (local dev, no production migration tracking) |
Platform behavior: The platform uses
__drizzle_migrationstable to track applied migrations. Runninggencow deploymultiple times is safe — only new migrations are applied.
Dependencies
Platform Packages (Pre-installed)
The following packages are included in the cloud runtime — no npm install needed:
| Package | Description |
|---|---|
@gencow/core |
Core framework (defineApi, procedure builders, scheduler, auth) |
drizzle-orm |
ORM and query builder |
better-auth |
Authentication system |
postgres |
PostgreSQL driver |
hono |
HTTP framework |
ai, @ai-sdk/* |
AI SDK (OpenAI, Anthropic, Google) |
zod |
Schema validation |
esbuild |
Build tools |
Third-Party Packages (Auto-installed)
Any additional npm packages in your package.json (e.g., langfuse, axios, cheerio) are automatically installed when you deploy:
gencow deploy # dev
gencow deploy --prod # production
# 📦 서드파티 패키지 감지: langfuse, cheerio
# → 클라우드 배포 시 자동 설치됩니다.Limits
| Limit | Value |
|---|---|
| Deploy bundle size | 100 MB max (gencow/ + package.json + lockfiles) |
Installed node_modules |
500 MB max after bun install |
| Install timeout | 60 seconds |
- On install failure: deployment continues but imports will fail at runtime
- Heavy packages like
puppeteer,sharp,tensorflowmay exceed the 500MB limit — use lightweight alternatives
⛔ Blocked modules:
child_process,vm,os,cluster,worker_threadsare blocked for security. OS-level isolation is handled by cowbox (Landlock + seccomp-bpf + cgroups v2).
Function Execution Limits
| Function Type | Time Limit |
|---|---|
query |
30 seconds |
mutation |
30 seconds |
httpRoute |
5 minutes |
cron |
10 minutes |
For long-running tasks, use
ctx.scheduler.runAfter()to split work across multiple function calls.⚠️ Cloud Warning:
scheduler.runAfter()is sleep-unsafe — if the app is idle and enters sleep mode, scheduled callbacks will be lost. For critical task chaining, usecronjobs or sequential calls from the frontend instead.
CI/CD Deployment
For automated deployments from GitHub Actions, GitLab CI, etc.:
1. Create a Deploy Token
Go to Dashboard → Settings → Deploy Tokens → Create Token
2. Set as CI Secret
# GitHub Actions: Settings → Secrets → GENCOW_TOKEN
# GitLab CI: Settings → CI/CD → Variables → GENCOW_TOKEN3. Use in CI Pipeline
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
- run: bun install
- run: npx gencow deploy # dev deploy
# - run: npx gencow deploy --prod # production deploy
env:
GENCOW_TOKEN: ${{ secrets.GENCOW_TOKEN }}When
GENCOW_TOKENis set,gencow deployuses it instead of interactive login.
Custom Domains
Connect your own domain to your Gencow app:
# Set domain
gencow domain set myapp.com
# Check DNS/TLS status
gencow domain status
# Remove domain
gencow domain removeDNS Setup
Add a CNAME record pointing to your app:
| Type | Name | Value |
|---|---|---|
| CNAME | myapp.com |
null-mint-9625.gencow.app |
TLS certificates are provisioned automatically via Let's Encrypt.
Deploy Commands Reference
| Command | Description |
|---|---|
gencow login |
Authenticate via browser |
gencow logout |
Clear saved credentials |
gencow whoami |
Show current user info |
gencow dev |
Real-time backend dev (watch + auto-deploy) |
gencow static [dir] |
Deploy static files to dev |
gencow static --prod [dir] |
Deploy static files to production (Pro+) |
gencow deploy |
Deploy backend to dev (one-shot) |
gencow deploy --prod |
Deploy backend to production (Pro+) |
gencow deploy --static [dir] |
Deploy backend first, then static files |
gencow deploy --rollback |
Roll back dev deployment |
gencow deploy --rollback --prod |
Roll back production deployment |
gencow deploy logs |
Follow server logs |
gencow deploy status |
Check container status |
gencow env list |
List cloud env vars |
gencow env list --prod |
List prod app env vars (Pro+) |
gencow env set K=V |
Set cloud env var (hot-reload) |
gencow env set K=V --prod |
Set prod app env var (Pro+) |
gencow env unset KEY |
Remove cloud env var |
gencow env push |
Push .env to cloud |
gencow env push --prod |
Push .env.production to prod app |
gencow domain set |
Connect custom domain |
gencow domain status |
Check domain DNS/TLS |
gencow domain remove |
Disconnect domain |
Next Steps
- AI Engine — Add AI capabilities
- Components —
gencow addcomponents - CLI Reference — All CLI commands