Deployment Overview
Deploying Juntos Applications
Juntos unlocks platforms Rails can’t reach—and works everywhere JavaScript runs.
Table of Contents
Sweet Spots
These targets require transpilation. Rails can’t run here; Juntos can:
| Target | Best For | Database Options |
|---|---|---|
| Browser | Offline-first, local-first, demos | Dexie, sql.js, PGlite |
| Vercel Edge | Global edge, auto-scaling | Neon, Turso, PlanetScale, Supabase |
| Deno Deploy | Edge, Deno/TypeScript native | Neon, Turso, PlanetScale, Supabase |
| Cloudflare Workers | Edge computing, maximum distribution | D1, Turso |
| Capacitor | iOS/Android mobile apps | Dexie, sql.js, HTTP-based |
| Electron | Desktop apps (macOS/Windows/Linux) | SQLite, sql.js, HTTP-based |
| Tauri | Lightweight desktop apps | sql.js, PGlite, HTTP-based |
Also Works
For traditional hosting, Juntos works but Rails does too. Reasons to choose Juntos on a server runtime:
- npm ecosystem — access to JavaScript libraries not available in Ruby
- Event-driven model — JavaScript’s async I/O may suit some workloads better than Ruby’s Global VM Lock (GVL)
- Unified codebase — one codebase across browser, edge, and server
| Target | Best For | Database Options |
|---|---|---|
| Fly.io | CLI-driven workflow, managed Postgres, native WebSockets | MPG (Managed Postgres) |
| Node.js | VPS, containers, widest compatibility | SQLite, PostgreSQL, MySQL |
| Bun | Fast startup, native SQLite | SQLite, PostgreSQL, MySQL |
| Deno | Secure by default, TypeScript | SQLite, PostgreSQL, MySQL |
Quick Comparison
| Aspect | Browser | Node.js | Fly.io | Vercel | Cloudflare | Capacitor | Electron | Tauri |
|---|---|---|---|---|---|---|---|---|
| Infrastructure | None (static) | Server/container | Container | On-demand | On-demand | App stores | User install | User install |
| Scaling | N/A | Manual | Automatic | Automatic | Automatic | Per-device | Per-device | Per-device |
| Cold starts | None | N/A | ~200-500ms | ~50-250ms | ~5-50ms | None | None | None |
| Database | Client-side | TCP/file | MPG (Postgres) | HTTP APIs | D1 binding | Client-side | File/client | Client-side |
| Native APIs | Limited | N/A | N/A | N/A | N/A | Full device | Full OS | Rust backend |
| Distribution | URL | Deploy | Deploy | Deploy | Deploy | App Store | DMG/EXE | DMG/EXE |
| Bundle size | N/A | N/A | N/A | N/A | N/A | ~5MB | ~150MB | ~3-10MB |
Choosing a Target
Choose Browser if:
- Your app works offline or local-first
- Data stays on the user’s device
- You want zero infrastructure
- Rails can’t do this
Choose Vercel, Deno Deploy, or Cloudflare if:
- You want global edge distribution
- You need auto-scaling and pay-per-request
- You want fast cold starts (~5-50ms)
- Rails can’t do this
Choose Fly.io if:
- You need native WebSocket support (Turbo Streams without Pusher)
- You want CLI-driven workflow (no dashboard copying)
- You want managed Postgres with automatic failover
- Rails works here too—but Juntos + MPG provides a streamlined CLI workflow
Choose Node.js, Bun, or Deno if:
- You need npm packages not available in Ruby
- Your workload benefits from JavaScript’s event-driven async model
- You want one codebase across browser, edge, and server
- Rails works here too—but Juntos has advantages
Choose Capacitor if:
- You want native iOS/Android apps
- You need device APIs (camera, GPS, push notifications)
- You want App Store/Google Play distribution
- Rails can’t do this
Choose Electron if:
- You want native desktop apps (macOS, Windows, Linux)
- You need OS integration (system tray, global shortcuts, file system)
- You want distributable installers (DMG, EXE, AppImage)
- Rails can’t do this
Choose Tauri if:
- You want lightweight desktop apps (~3-10MB vs Electron’s ~150MB)
- Lower memory usage is important
- You’re comfortable with Rust for custom native features
- You want the smallest possible bundle size
- Rails can’t do this
Default Target Inference
When you don’t specify a target, Juntos infers it from your database:
bin/juntos up -d dexie # → browser
bin/juntos up -d sqlite # → node
bin/juntos up -d neon # → vercel
bin/juntos up -d d1 # → cloudflare
bin/juntos up -d mpg # → fly
Override with -t:
bin/juntos up -t node -d neon # Force Node.js with Neon
Hybrid Development
You don’t need to hit remote databases during development. Use the familiar config/database.yml pattern—a local database for development, a cloud database for production.
Recommended Pairings
| Deploy Target | Prod Database | Dev Adapter | Dev Target | Notes |
|---|---|---|---|---|
| Cloudflare Workers | d1 | sqlite | node | Same SQL dialect |
| Vercel Edge | neon | pglite | browser | No server needed |
| Vercel Edge | turso | sqlite | node | Same SQL dialect |
| Deno Deploy | neon | pg | deno | Requires local PostgreSQL |
| Fly.io | mpg | sqlite | node | Local SQLite, prod Postgres |
Example Configuration
# config/database.yml
development:
adapter: sqlite
database: db/development.sqlite3
production:
adapter: d1
database: myapp_production
# Development: instant feedback, no cloud round-trips
bin/juntos up -d sqlite
# Production: deploy to Cloudflare with D1
bin/juntos deploy -d d1
The SQL dialect matches between SQLite and D1, so your migrations and queries work in both environments.
Offline-First Browser Apps
The browser target enables offline-first applications that sync with a Rails backend:
- Browser app — runs entirely client-side with IndexedDB (Dexie)
- Rails API — traditional server for sync and shared data
- Sync on reconnect — browser app treats Rails as an API when connectivity returns
This pattern works well for:
- Mobile apps in spotty connectivity
- Field data collection
- Event scoring/judging systems
- Any scenario where the app must work without internet
# Same models power both apps
development:
adapter: dexie # Browser app
database: myapp_dev
production:
adapter: pg # Rails API backend
url: <%= ENV['DATABASE_URL'] %>
Database Setup Guides
For detailed setup instructions, see the Database Overview:
- Neon — Serverless PostgreSQL
- Turso — SQLite at the edge
- PlanetScale — Serverless MySQL
- Supabase — Full backend platform